package com.interview.algorithms.dp;
/**
* Created with IntelliJ IDEA.
* User: stefanie
* Date: 9/19/14
* Time: 1:40 PM
*
* [Introduction to Algorithm Chp.15] The matrix multiply
* There is M matrix, A1 A2 .. AM, write code to find the smallest cost ways to make these M matrix could multiply.
* (A1 * (A2 * A3)) or ((A1 * A2) * A3) give the same answer, but may cause different of computing effect when A1 is a very small matrix
* And A1*A1 could multiply when dimensionality is the same, so d[N] save the dimensions, Ai's dimension is di-1 and di
*
* define opt[i][j] as the min cost of matrix i multiply to matrix j
* opt[i][j] = min{ opt[i][k] + opt[k][j] + d[i-1] * d[k] * d[j] } for all the k in [i,j-1]
*
*
* Since we need opt[i][k] calculated before opt[i][j], so the loop can't be for each i, each j, it should have length
* for length from 2 - N-1
* for i from 1 to N - l //the start
* j = i + l - 1; //the end
* for k from i to j find the min opt[i][j] and mark the split in sol[i][j]
*/
public class C12_22_MatrixMultiply {
static class Result {
int cost;
String combination;
}
public static Result count(int[] dim) {
int N = dim.length;
int[][] opt = new int[N][N];
int[][] sol = new int[N][N];
for (int i = 1; i < N; i++) opt[i][i] = 0;
for (int l = 2; l < N; l++) { // l is the length of matrix chain
for (int i = 1; i < N - l + 1; i++) { // i is the start of the chain
int j = i + l - 1; // j is the end of the chain
opt[i][j] = Integer.MAX_VALUE;
for (int k = i; k < j; k++) {
int ten = opt[i][k] + opt[k + 1][j] + dim[i - 1] * dim[k] * dim[j];
if (ten < opt[i][j]) {
opt[i][j] = ten;
sol[i][j] = k;
}
}
}
}
Result result = new Result();
result.cost = opt[1][N - 1];
result.combination = buildCombination(N, sol);
return result;
}
private static String buildCombination(int N, int[][] sol) {
StringBuilder builder = new StringBuilder();
for (int i = 1; i < N; i++) {
builder.append((char) ('A' + (i - 1)));
}
return addBracket(builder.toString(), 1, N - 1, sol[1][N - 1], sol);
}
private static String addBracket(String str, int i, int j, int k, int[][] sol) {
if (str.length() <= 2) return str;
String a = str.substring(i - 1, k);
String b = str.substring(k, j);
StringBuilder builder = new StringBuilder();
builder.append("(");
builder.append(addBracket(a, i, k, sol[i][k], sol));
builder.append(")(");
builder.append(addBracket(b, 1, j - k, sol[k][j], sol));
builder.append(")");
return builder.toString();
}
}