AcWing 1070. 括号配对
考察:区间DP
思路:
与上题区别在于()是一类,()[]也是一类,两类需要分别处理,第一类和上题一样处理,分11 10 01 00(i,j是否在里面)讨论,第二类分为第一个括号序列和右边其他的括号序列,因为第一个括号序列无法表达,只能用包含它的f[i,k],所以第二类是f[i,k]+f[k+1,j]
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 const int N = 110; 6 char s[N]; 7 int f[N][N]; 8 bool check(int i,int j) 9 { 10 if(s[i]=='('&&s[j]==')') return 1; 11 if(s[i]=='['&&s[j]==']') return 1; 12 return 0; 13 } 14 int main() 15 { 16 scanf("%s",s+1); 17 int sl = strlen(s+1); 18 for(int i=1;i<=sl;i++) f[i][i] = 1; 19 for(int len=2;len<=sl;len++) 20 for(int l=1;l+len-1<=sl;l++) 21 { 22 int r = l+len-1; 23 f[l][r] = 0x3f3f3f3f; 24 if(check(l,r)) f[l][r] = f[l+1][r-1];//进入括号里不一定最优,存在()()的数据,需要分隔点 25 for(int k=l;k<=r;k++) 26 f[l][r] = min(f[l][r],f[l][k]+f[k+1][r]); 27 } 28 printf("%d\n",f[1][sl]); 29 }
补一道差不多的题,这道题问的是合法的最长序列.分为两类一类是((()))另一类是()().
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <map> 6 using namespace std; 7 const int N = 110; 8 char s[N]; 9 int f[N][N]; 10 map<char,char> mp; 11 int main() 12 { 13 mp['('] = ')'; mp['['] = ']'; 14 while(scanf("%s",s+1)&&s[1]!='e') 15 { 16 int n = strlen(s+1); 17 memset(f,0,sizeof f); 18 for(int len=2;len<=n;len++) 19 for(int l=1;l+len-1<=n;l++) 20 { 21 int r = l+len-1; 22 if(mp[s[l]]==s[r]) f[l][r] = f[l+1][r-1]+2; 23 for(int k=l;k<r;k++) 24 f[l][r] = max(f[l][r],f[l][k]+f[k+1][r]); 25 } 26 printf("%d\n",f[1][n]); 27 } 28 return 0; 29 }