UVA 1626 Brackets sequence (最优矩阵链乘)

时间:2022-12-29 08:13:48
如何理解紫书上的递推方式?
1. 首先,由状态转移方程中d[i][j]的其中一个状态d[i + 1][j - 1]可以得到枚举顺序。
2. 其次,d[i][j]还可由两个子串的状态得到,而逆序枚举时所有子串的结果已经取得。
3. 对这个递推过程不应该理解成一个二维的平面,应当作为区间来考虑他的状态转移。
#include <iostream>#include <cstring>
#include <cstdio>

using namespace std;
const int maxn = 105;
int d[maxn][maxn];

char s[maxn];

bool match(char a, char b) { return (a == '(' && b == ')') || (a == '[' && b == ']'); }

void dp(int n) {
for(int i = 0; i < n; ++i)
d[i][i + 1] = 1, d[i][i] = 0;
for(int i = n - 2; i >= 0; --i) {
for(int j = i + 2; j <= n; ++j) {
int &t = d[i][j];
t = n;
if(match(s[i], s[j - 1])) t = min(t, d[i + 1][j - 1]);
for(int k = i + 1; k <= j - 1; ++k) {
t = min(t, d[i][k] + d[k][j]);
}
}
}

/*cout << "debug" << endl;
for(int i = 0; i < n; ++i)
for(int j = i + 1; j <= n; ++j)
printf("i = %d, j = %d, d = %d\n", i, j, d[i][j]);
cout << "debug" << endl;*/
}

void print(int i, int j) {
if(i >= j) return;
if(i == j - 1) {
if(s[i] == '(' || s[i] == ')') printf("()");
else printf("[]");
return;
}

int ans = d[i][j];
if(match(s[i], s[j - 1]) && ans == d[i + 1][j - 1]) {
putchar(s[i]);
print(i + 1, j - 1);
putchar(s[j - 1]);
}
else {
for(int k = i + 1; k < j; ++k) {
if(ans == d[i][k] + d[k][j]) {
print(i, k); print(k, j);
return;
}
}
}
}

int main() {
/*
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
*/
int t;
cin >> t;
getchar();
while(t--) {
gets(s);
gets(s);
int len = strlen(s);
dp(len);
print(0, len);
cout << endl;
if(t) cout << endl;
//cout << d[0][len] << endl;
}
return 0;
}