POJ 2955 括号匹配,区间DP
题意:给你一些括号,问匹配规则成立的括号的个数。
思路:这题lrj的黑书上有,不过他求的是添加最少的括号数,是的这些括号的匹配全部成立。
我想了下,其实这两个问题是一样的,我们可以先求出括号要匹配的最少数量,那么设原来括号的数量为l , 添加了l' 。
那么其实原来括号匹配成功的括号数就是((l + l') / 2 - l') * 2。
#define N 105 char a[N] ; int dp[N][N] ; int f[N][N] ; int check(int i ,int j) { if(a[i] == '[' && a[j] == ']')return 1 ; if(a[i] == '(' && a[j] == ')')return 1 ; return 0 ; } void init() { mem(dp ,0) ; mem(f ,0) ; } int main() { while(cin >> a) { if(strcmp(a , "end") == 0)break ; init() ; int l = strlen(a) ; for (int i = 0 ; i < l ; i ++ ) { dp[i][i] = 1 ; dp[i + 1][i] = 0 ; } for (int i = 1 ; i <= l ; i ++ ) { for (int j = 0 ; j + i - 1 < l ; j ++ ) { int s = j ; int e = j + i - 1 ; dp[s][e] = 0 ; if(check(s ,e))dp[s][e] = min(dp[s][e] , dp[s + 1][e - 1]) ; if(a[s] == '[' || a[s] == '(')dp[s][e] = min(dp[s][e] , dp[s + 1][e] + 1) ; if(a[e] == ']' || a[e] == ')')dp[s][e] = min(dp[s][e] , dp[s][e - 1] + 1) ; for (int k = s ; k < e ; k ++ ){ dp[s][e] = min(dp[s][e] , dp[s][k] + dp[k + 1][e]) ; } } } cout << ((l + dp[0][l - 1]) / 2 - dp[0][l - 1]) * 2 << endl; } return 0 ; }
当然,按照思路来写应该是这样的区间dp。
#define N 105 int dp[N][N] ; char a[N] ; bool check(int i ,int j){ if(a[i] == '[' && a[j] == ']')return 1 ; if(a[i] == '(' && a[j] == ')')return 1 ; return 0 ; } int main() { int T ; while(cin >> a){ if(strcmp(a ,"end") == 0)break ; int l = strlen(a) ; mem(dp , 0) ; for (int i = 2 ; i <= l ; i ++ ){ for (int j = 0 ; j + i - 1 < l ; j ++ ){ int s = j ; int e = j + i - 1 ; if(check(s ,e ))dp[s][e] = max(dp[s][e] , dp[s + 1][e - 1] + 2) ; for (int k = s ; k < e ; k ++ ){ dp[s][e] = max(dp[s][e] , dp[s][k] + dp[k + 1][e]) ; } } } cout << dp[0][l - 1] << endl; } return 0 ; }