poj 2955"Brackets"(区间DP)

传送门

https://www.cnblogs.com/violet-acmer/p/9852294.html

题意:

  给你一个只由 '(' , ')' , '[' , ']' 组成的字符串s[ ],求最大匹配?

题解:

  定义dp[ i ][ j ] : 从第i个字符到第j个字符的最大匹配。

  步骤:

    (1) : 如果s[ i ] 与 s[ j ]匹配,那么dp[ i ][ j ] =  2+dp[ i+1 ][ j-1 ];反之,dp[ i ][ j ] = 0;

    (2) : 接下来,从 i 到 j 将区间划分成两部分[ i , k ]和[ k+1 , j ],( i ≤ k ≤ j-1 ),状态转移方程为

      dp[ i ][ j ]=max( dp[ i ][ j ] , dp[ i ][ k ]+dp[ k+1 ][ j ] );

扫描二维码关注公众号,回复: 4531998 查看本文章

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 #define mem(a,b) memset(a,b,sizeof(a))
 6 const int maxn=100+10;
 7 
 8 char s[maxn];
 9 int dp[maxn][maxn];
10 
11 // (int)'(' = 40,(int)')' = 41;
12 // (int)'[' = 91,(int)']' = 93;
13 bool isMatch(int i,int j){//判断s[i]与s[j]是否匹配
14     return (s[j]-s[i] == 1 || s[j]-s[i] == 2) ? true:false;
15 }
16 int Solve()
17 {
18     int sLen=strlen(s);
19     int res=0;
20     for(int i=0;i < sLen;++i)
21     {
22         dp[i][i]=0;
23         dp[i][i+1]=(isMatch(i,i+1) ? 2:0);
24         res=dp[i][i+1];
25     }
26     for(int len=3;len <= sLen;++len)//区间长度
27     {
28         for(int i=0;i+len-1 < sLen;++i)
29         {
30             int j=i+len-1;
31             dp[i][j]=(isMatch(i,j) ? 2+dp[i+1][j-1]:0);
32             for(int k=i;k < j;++k)
33                 dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]);
34             res=max(res,dp[i][j]);
35         }
36     }
37     return res;
38 }
39 int main()
40 {
41 //    freopen("C:\\Users\\lenovo\\Desktop\\in.txt\\poj2955.txt","r",stdin);
42     while(scanf("%s",s) && s[0] != 'e')
43         printf("%d\n",Solve());
44 
45     return 0;
46 }
View Code

  分析:

    能使用区间DP,必须得满足两个条件:

    (1) : 问题具有最优子结构

      如果区间对于状态转移方程:dp[ i ][ j ]=max( dp[ i ][ j ] , dp[ i ][ k ]+dp[ k+1 ][ j ] );

      如果子结构dp[ i , k ],dp[ k+1 , j ]所求的解为最优解,那么dp[ i , j ]必定也是最优解,反之亦成立。

    (2) : 无后效性

      区间[ i , j ]的子区间 [ i , k ] 和 [ k+1 , j ] 是通过何种方式取得最优解的并不影响 [ i , j ] 是以何种方式取得最优解

猜你喜欢

转载自www.cnblogs.com/violet-acmer/p/10127596.html