题意 : 中文题不详述。
思路 : 本来以为只是个小模拟,没想到是个区间DP,还是对DP不了解。
DP[i][j]代表着从字符串 i 位置到 j 位置需要的最小括号匹配。
所以初始化的DP[i][i] = 1 ;第i个位置的话需要匹配的最小括号数是1。
状态转移方程 :如果第i个位置和第j个位置的两个括号是匹配的,那么DP[i][j] = DP[i+1][j-1],相当于两边分别往里缩了一个;当i < j 时,DP[i][j] = DP[i][k]+DP[k+1][j] ;
黑书上对于这个问题有详细的解释。我用的就是黑书上的方法二,不过方法二有点赘余,就是我代码中注释的部分,加上也对,不加也可。
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 5 using namespace std ; 6 7 int dp[210][210] ; 8 char ch[123] ; 9 10 int main() 11 { 12 int n ; 13 scanf("%d",&n) ; 14 getchar() ; 15 while(n--) 16 { 17 scanf("%s",ch); 18 memset(dp,0,sizeof(dp)) ; 19 int len = strlen(ch) ; 20 for(int i = 0 ; i < len ; i++) 21 dp[i][i] = 1 ; 22 for(int h = 1 ; h < len ; h++) 23 { 24 for(int i = 0 ; i < len-h ; i++) 25 { 26 int j = h+i ; 27 dp[i][j] = 99999999 ; 28 if((ch[i] == '('&&ch[j] == ')') || (ch[i] == '[' && ch[j] == ']')) 29 dp[i][j] = min(dp[i][j],dp[i+1][j-1]) ; 30 // else if(ch[i] == '(' || ch[i] == '[') 31 // dp[i][j] = min(dp[i][j],dp[i+1][j])+1 ; 32 // else if(ch[j] == ')' || ch[j] == ']') 33 // dp[i][j] = min(dp[i][j],dp[i][j-1])+1 ; 34 for(int k = i ; k <= j ; k++) 35 dp[i][j] = min(dp[i][j],dp[i][k-1]+dp[k][j]) ; 36 } 37 } 38 printf("%d ",dp[0][len-1] ) ; 39 } 40 return 0 ; 41 }