1804: Bracket matching (2)
Time Limit: 1 Sec Memory Limit: 64 MB[ Commit ][ Status ][ Discussion Board ]
Topic description
For example:
[] is matched
([]) [] is matched
((] is not matched
([)] is not matched
enter
output
sample input
4
[]
([])[]
((]
([)]
Sample output
0
0
3
2
source
Interval DP
Turn:
The meaning of the question is to say that given a string containing four characters of '(', ')', '[', ']', it is judged that at least a few characters need to be added to match the parentheses of the given string.
Interval dynamic programming, let dp[i][j] represent the minimum characters that need to be added from position i to position j in string s (i <= j)
There are two cases:
1、dp[i][j] = dp[i+1][j] + 1;
Indicates: there is no parenthesis matching s[i] between i and j, then a character must be added to match it, and the problem is transformed into: the minimum number of characters that need to be added from the i+1 position to the j position + 1.
2、dp[i][j] = min{ dp[i+1][k-1] + dp[k+1][j] }; (i < k <= j)
Representation: find a k between i and j so that s[i] matches s[k], then the problem is transformed into: the minimum number of characters to be added from i+1 to k-1 + from k The minimum number of characters to be added between +1 and j (ie dp[i+1][k-1] + dp[k+1][j] ). Since there may be more than one k, take the smallest among all the k cases.
After finding the two cases, and then finding the minimum value between the two, you can directly assign the initial value of dp[i][j] to dp[i+1][j]+1, and then proceed to the second case solution
After the dynamic transfer equation comes out, it is necessary to judge how many layers of loops to write and the starting point and end point of each layer of loops. It can be seen from the equation that there are 3 layers of loops (i, j, k). For dp[i][j], it must be First find the first j of the rows after i, so there are two methods of looping. I use the second method, which is relatively easy to understand. As shown below.
Method 1: Update from left to right Method 2: Update from bottom to top
Initialization: add at least one character when there is only one character, so dp[i][i] = 1;
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; char str[110]; int judge(int x,int y){//Judging whether str[x] and str[y] are paired if(str[x]=='('&&str[y]==')'||str[x]=='['&&str[y]==']') return 1; else return 0; } int main(){ int N; scanf("%d",&N); int dp[110][110]; while(N--){ memset(dp,0,sizeof(dp)); scanf("%s",str); int len=strlen(str); for(int i=0;i<len;i++){ dp[i][i]=1; } for(int i=len-2;i>=0;i--){ for(int j=i;j<len;j++){ dp[i][j]=dp[i+1][j]+1;//赋初值为第一种情况(在i和j之间没有str[i]的),因为有两种情况并且最后要取两种情况的最小值,所以先给初始情况赋值为第一种情况 //(一共是两种情况,第一种是i和j之间没有字符可以匹配str[i],所以需要在i和j之间加一个括号,问题就转化为在第i+1和j之间需要加的括号数+1 //另一种是i和j之间本身就存在着和str[i]搭配的括号str[k],那么问题就转化为在第i+1和第k-1之间需要加的最小值和在k+1和j之间需要加的最小括号数的和) for(int k=i+1;k<=j;k++){ if(judge(i,k)){//在i跟j之间存在着str[i]的配对括号 dp[i][j]=min(dp[i][j],dp[i+1][k-1]+dp[k+1][j]);//因为k可能有多个,所以在所有的情况中取最小的 } } } } printf("%d\n",dp[0][len-1]); } return 0; }