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 }
POJ

 

posted @ 2021-02-10 20:11  acmloser  阅读(70)  评论(0编辑  收藏  举报