南陽理工學院動態規劃專題 括號問題2 總結
南陽理工學院動態規劃專題括號問題2總結
這道題目初看起來很簡單,但是我從看題到思考,到做題ac足足花了一個晚上加一個下午的時間,我也有到網上找程式碼的習慣,但是都是遞迴,特別蛋疼,我想用正統的動歸去做,於是就開始了不一樣的艱難探索之旅。
分析過程:
使用char str[1001]這個字元陣列儲存最初輸入的括號序列,使用dp[1001][1001]這個陣列儲存中間結果,dp[i][j]的意思是從下標為i的字元到下標為j的字元的子問題最少要加多少個括號才能規範化。首先dp陣列初始化為零,顯然dp[i][i]=1;至於dp[i][i+1],當str[i][i+1]配對的時候=0,當str[i][i+1]不配對的時候=2
如果str[i]和str[j]配對則分為兩種情況:
1. i->(…)(…)<-j,則dp[i][j]=min{dp[i][k]+dp[k+1][j]};
2. i->(..(..)..)<-j,則dp[i][j]=dp[i+1][j-1],因為之前dp[i+1][j-1]已經計算過,因此直接使用即可。
如果str[i]和str[j]不配對分為四種情況:
1. 在str[i+1]到str[j]的字串當中有與str[i]配對的括號,其對應的下標序列為k1,k2,k3,…
則dp[i][j]=min{dp[i][k1]+dp[k1+1][j], dp[i][k2]+dp[k2+1][j],dp[i][k3]+dp[k3+1][j],…};
2. 當不存在與str[i]相匹配的括號時直接使用dp[i][j]=dp[i+1][j]+1;
3. 在str[i]到str[j-1]的字串當中有與str[j]配對的括號,其對應的下標序列為k1,k2,k3,…
則dp[i][j]=min{dp[i][k1-1]+dp[k1][j], dp[i][k2-1]+dp[k2][j],dp[i][k3-1]+dp[k3][j],…};
4. 不存在與str[i]相匹配的括號時直接使用dp[i][j]=dp[i][j-1]+1;
計算完成後dp[0][strlen(str)-1]即是計算結果。
Ac程式碼:
#include<iostream> #include<stdio.h> #include<string.h> #define INF 100000000 using namespace std; char str[101]; int dp[101][101]; bool match(char ch1,char ch2) { if(ch1=='('&&ch2==')')return true; if(ch1=='['&&ch2==']')return true; return false; } int main() { int cas; cin>>cas; while(cas--) { int top=-1; memset(str,0,sizeof(str)); cin>>str; int l1=strlen(str); if(l1==0) { cout<<"0"<<endl; continue; } for(int i=0;i<l1;i++)dp[i][i]=1; for(int i=0;i<l1-1;i++) { if(match(str[i],str[i+1])) { dp[i][i+1]=0; } else{dp[i][i+1]=2;} } for(int k=2;k<l1;k++) { for(int i=0;i+k<l1;i++) { int j=i+k; if(match(str[i],str[j])) { int min1=INF; for(int kk=i+1;kk<j;kk++) { intt=dp[i][kk]+dp[kk+1][j]; if(min1>t) min1=t; } int min2=dp[i+1][j-1]; dp[i][j]=min(min1,min2); } else { int min1=INF; for(int kk=i+1;kk<j;kk++) { if(match(str[i],str[kk]))//檢查左端 { intt=dp[i][kk]+dp[kk+1][j]; if(min1>t) min1=t; } } int min2=dp[i+1][j]+1; int min3=IN for(intkk=i+1;kk<j;kk++)//檢查右端 { if(match(str[kk],str[j])) { intt=dp[i][kk-1]+dp[kk][j]; if(min3>t) min1=t; } } int min4=dp[i][j-1]+1; dp[i][j]=min(min(min1,min2),min(min3,min4)); } } } cout<<dp[0][l1-1]<<endl; // for(int i=0;i<l1;i++) // { // for(int j=0;j<l1;j++) // { // cout<<dp[i][j]<<' '; // } // cout<<endl; // } } }
括號匹配(二)
時間限制:1000 ms | 記憶體限制:65535 KB
難度:6
描述
給你一個字串,裡面只包含"(",")","[","]"四種符號,請問你需要至少新增多少個括號才能使這些括號匹配起來。
如:
[]是匹配的
([])[]是匹配的
((]是不匹配的
([)]是不匹配的
輸入
第一行輸入一個正整數N,表示測試資料組數(N<=10)
每組測試資料都只有一行,是一個字串S,S中只包含以上所說的四種字元,S的長度不超過100
輸出
對於每組測試資料都輸出一個正整數,表示最少需要新增的括號的數量。每組測試輸出佔一行
樣例輸入
4
[]
([])[]
((]
([)]
樣例輸出
0
0
3
2
來源
上傳者