両端の距離が小さい部分問題から解がうまっていくタイプのDPの典型問題です。
問題
Optimal Array Multiplication Sequence
ソースコード
const long long INF = 1LL<<60;
int n;
int r[16], c[16];
int mid[16][16];
long long dp[16][16];
inline string toString(int x) {
ostringstream os;
os << "A" << x;
return os.str();
}
string printResult(int left, int right) {
if (right - left == 0)
return toString(left+1);
return "(" + printResult(left, mid[left][right]) + " x " + printResult(mid[left][right]+1, right) + ")";
}
void solve(int &t) {
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
dp[i][j] = INF;
for (int i = 0; i < n; i++)
dp[i][i] = 0;
for (int k = 1; k < n; k++) {
for (int i = 0; i + k < n; i++) {
int j = i + k;
for (int m = i; m < j; m++) {
long long tmp = dp[i][m] + dp[m+1][j] + r[i] * c[j] * c[m];
if (dp[i][j] > tmp) {
dp[i][j] = tmp;
mid[i][j] = m;
}
}
}
}
cout << "Case " << ++t << ": " << printResult(0, n-1) << endl;
}
int main() {
int t = 0;
while (scanf("%d", &n) == 1) {
if (n == 0)
break;
for (int i = 0; i < n; i++)
scanf("%d %d", r+i, c+i);
solve(t);
}
return 0;
}
0 件のコメント:
コメントを投稿