http://acm.nyist.net/JudgeOnline/problem.php?pid=15
dp[i][j]表示从i到j至少需要添加多少个括号才能满足匹配条件.
初始化:
if(i == j)
dp[i][j] = 1;
else
dp[i][j] = INF;
状态转移:
当i < j时;
if(match(str[i], str[j])) dp[i][j] = min(dp[i][j], d[i + 1][j - 1]);
然后分割区间, 找最优分割点k. (i <= k <= j);
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]);
循环时, 遍历区间(i...j)的起点i以及区间长度len, len从小到大依次递增.
即循环找出每一段起点为i长度为len的区间的最优解, 慢慢扩大至整个区间.即最终问题的解!
#include <stdio.h> #include <string.h> #include <math.h> #include <iostream> #include <algorithm> #include <string> #include <queue> #include <stack> #include <vector> #include <list> #include <map> #include <set> #include <iomanip> #define CL(x,v); memset(x,v,sizeof(x)); #define INF 1<<29 #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int N = 100 + 10; int dp[N][N]; char str[N]; int match(char ch1, char ch2) { if((ch1 == '(' && ch2 == ')') || (ch1 == '[' && ch2== ']')) return 1; return 0; } int main() { int t; scanf("%d", &t); while(t--) { CL(dp, 0); scanf("%s", str); int length = strlen(str); for(int i = 0; i < length; ++i) dp[i][i] = 1; for(int len = 1; len < length; ++len) { for(int i = 0; i < length - len; ++i) { int j = i + len; dp[i][j] = INF; if(match(str[i], str[j])) dp[i][j] = min(dp[i][j], dp[i + 1][j - 1]); for(int k = i; k <= j; ++k) dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]); } } cout << dp[0][length - 1] << endl; } return 0; }
原文地址:http://blog.csdn.net/u012944079/article/details/40111503