poj2955Brackets【区间dp 括号匹配】

给你()【】组成的序列,问你最长能构成多少个匹配的。开始的错误思路,又是思维定势,觉得应该是把区间分两半,左边dp值加右边dp值再加左边区间和右边区间凑到一起能多形成的括号数,思路是这么回事没问题,中间输出了n多中间变量才发现自己这里求错了,左边和右边凑到一起多形成的不可以用min(左边左括号的数量,右边右括号的数量),有严重的思维漏洞啊!左边左括号的可以与左边右括号匹配,右边右括号也可以和右边左括号的匹配啊,照我那么求就重复了==那怎么求啊,想了半天没想到好的求一定区间内未匹配左括号、右括号的数量方法

无奈搜题解,用深搜解决啊,深搜的参数是区间左右端点,很明显如果左端点小于等于右端点,返回0,左端点==右端点-1,若能配对,返回2,不能配对返回0.重点是更长的情况:

用左顶点或是右端点尝试与中间配对,配对成功+2,循环一圈取最大。网上都是用左顶点写的,我试着改成右端点,也对了。初始化也得改

右顶点写法:

/*****************
poj2955
2016.2.19
200K	32MS	C++	1042B
*****************/
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[102][102],len;
char str[105];
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int dfs(int l,int r)
{
    if(dp[l][r]!=-1) return dp[l][r];
    if(l>=r)
    {
        dp[l][r]=0;
        return 0;
    }
    if(l==r-1)
    {
        if((str[l]=='('&&str[r]==')')||(str[l]=='['&&str[r]==']')) return dp[l][r]=2;
        else return dp[l][r]=0;
    }
    dp[l][r]=dfs(l,r-1);
    for(int k=l;k<r;k++)
    {
        if((str[r]==')'&&str[k]=='(')||(str[r]==']'&&str[k]=='['))
        dp[l][r]=max(dp[l][r],dfs(l,k-1)+dfs(k+1,r-1)+2);
    }
    return dp[l][r];
}
int main()
{
   // freopen("cin.txt","r",stdin);
    while(~scanf("%s",str))
    {
        if(strcmp(str,"end")==0) break;
        len=strlen(str);
        for(int i=len;i>0;i--) str[i]=str[i-1];
       // printf("%s",str);
        memset(dp,-1,sizeof(dp));
        printf("%d\n",dfs(1,len));
    }
    return 0;
}
左顶点写法

#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[102][102],len;
char str[105];
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int dfs(int l,int r)
{
    if(dp[l][r]!=-1) return dp[l][r];
    if(l>=r)
    {
        dp[l][r]=0;
        return 0;
    }
    if(l==r-1)
    {
        if((str[l]=='('&&str[r]==')')||(str[l]=='['&&str[r]==']')) return dp[l][r]=2;
        else return dp[l][r]=0;
    }
    dp[l][r]=dfs(l+1,r);
    for(int k=l+1;k<=r;k++)
    {
        if((str[l]=='('&&str[k]==')')||(str[l]=='['&&str[k]==']'))
        dp[l][r]=max(dp[l][r],dfs(l+1,k-1)+dfs(k+1,r)+2);
    }
    return dp[l][r];
}
int main()
{
   // freopen("cin.txt","r",stdin);
    while(~scanf("%s",str))
    {
        if(strcmp(str,"end")==0) break;
        len=strlen(str);
        for(int i=len;i>0;i--) str[i]=str[i-1];
       // printf("%s",str);
        memset(dp,-1,sizeof(dp));
        printf("%d\n",dfs(1,len));
    }
    return 0;
}


你可能感兴趣的:(dp,poj)