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;

}

 

你可能感兴趣的:(sequence)