ACM-ICPC Live Archive 2451 Brackets Sequence

动态规划

poj 1141   ural 1183   zoj 1463  都是相同的题目,黑书DP的例题

输入比较恶心,有空串。递推的时间是1s多,记忆化的时间是4.3s勉强过,原理不说了百度各种有

 

/*
1.dp[i][j]=dp[i+1][j-1] , p[i][j]=-1 , --->p[i+1][j-1]
2.dp[i][j]=dp[i+1][j]+1 , p[i][j]=-2 , --->p[i+1][j]
3.dp[i][j]=dp[i][j-1]+1 , p[i][j]=-3 , --->p[i][j-1]
4.dp[i][j]=dp[i][k]+dp[k+1][j] , p[i][j]=k , --->p[i][k],p[k][j]
5.p[i][j]初始化为0
*/
#include <cstdio>
#include <cstring>
#define MAX 110
#define INF 0x3f3f3f3f


char s[MAX];
int dp[MAX][MAX],p[MAX][MAX],n;

int min(int a , int b , int *c)
{
    if(a>b) {(*c)=1; return b;}
    else    {(*c)=0; return a;}
    //c是用于标记有没有更新最小值
}

void print(int i ,int j)
{
    if(i>j) return ;
    if(p[i][j]==-1)
    {
        printf("%c",s[i]);
        print(i+1,j-1);
        printf("%c",s[j]);
        return ;
    }
    if(p[i][j]==-2)
    {
        printf("%c",s[i]);
        print(i+1,j);
        if(s[i]=='(') printf(")");
        else if(s[i]=='[') printf("]");
        return ;
    }
    if(p[i][j]==-3)
    {
        if(s[j]==')') printf("(");
        else if(s[j]==']') printf("[");
        print(i,j-1);
        printf("%c",s[j]);
        return ;
    }
    int k=p[i][j];
    print(i,k);
    print(k+1,j);
    return ;

}

int dfs(int i ,int j)
{
    if(i>j) {  return dp[i][j]=0; }  //错位
    if(dp[i][j]!=-1) return dp[i][j];

    int c;
    dp[i][j]=INF;
    if( (s[i]=='(' && s[j]==')') || (s[i]=='[' && s[j]==']') )
    {
        dp[i+1][j-1]=dfs(i+1,j-1);
        dp[i][j]=min(dp[i][j] , dp[i+1][j-1] , &c);
        if(c) p[i][j]=-1;
    }
    if(s[i]=='(' || s[i]=='[')
    {
        dp[i+1][j]=dfs(i+1,j);
        dp[i][j]=min(dp[i][j] , dp[i+1][j]+1 , &c);
        if(c) p[i][j]=-2;
    }
    if(s[j]==')' || s[j]==']')
    {
        dp[i][j-1]=dfs(i,j-1);
        dp[i][j]=min(dp[i][j] , dp[i][j-1]+1 , &c);
        if(c) p[i][j]=-3;
    }

    for(int k=i; k<j; k++) //分块
    {
        dp[i][k]=dfs(i,k);
        dp[k+1][j]=dfs(k+1,j);
        dp[i][j]=min(dp[i][j] , dp[i][k]+dp[k+1][j] , &c);
        if(c) p[i][j]=k;
    }
    return dp[i][j];
}

int main()
{
    int Case;
    scanf("%d",&Case);
    getchar();
    while(Case--)
    {
        getchar();
        gets(s+1);
        if(s[1]=='\0')
        {
            printf("\n");
            if(Case) printf("\n");
            continue;
        }
        n=strlen(s+1);
        memset(dp,-1,sizeof(dp));
        memset(p,0,sizeof(p));
        for(int i=1; i<=n; i++)
        {
            dp[i][i]=1;
            if(s[i]=='(' || s[i]=='[')
                p[i][i]=-2;
            else  p[i][i]=-3;
        }
        dfs(1,n);
        //printf("%d\n",dp[1][n]);
        print(1,n);
        printf("\n");
        if(Case) printf("\n"); 
    }
    return 0;
}

 

posted @ 2013-03-02 23:46  Titanium  阅读(469)  评论(0编辑  收藏  举报