UVA1626 简单DP

来源:互联网 发布:ios内购软件 编辑:程序博客网 时间:2024/06/06 01:45

题意

输入n个样例,每个样例为包含的字符串,添加最少的字符,使得字符串中的匹配。

题解

设从i到j的字符串最少需要增加dp[i][j]个字符,如果字符i和字符j匹配,则状态可转移到dp[i+1][j-1]。如果字符串有两个以上的字符,则状态可转移到dp[i][k]+dp[k+1][j]。动态规划处理完毕后,输出解时可以重新检查决策,如果最优状态是转移到dp[i+1][j-1],则输出字符i和字符j,并进行递归输出i+1到j-1之间的字符串。如果最优状态是转移到dp[i][k]+dp[k+1][j],则递归输出i到k和k+1到j之间的字符串。

注意事项

这道题存在空字符串的情况,所以要用gets(),而不能用scanf(“%s”)。另外,本题输出格式比较特殊,两个解之间必须要以空行分隔,但最后一个解后无空行,这点需要特别注意。

代码

#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;int n;int dp[110][110];char ch[120];bool match(char a,char b){    if(a=='['&&b==']')        return true;    else if(a=='('&&b==')')        return true;    else         return false;}void dpMethod(){    for(int i=0;i<n;i++){        dp[i][i]=1;        dp[i+1][i]=0;    }    for(int i=n-2;i>=0;i--){        for(int j=i+1;j<n;j++){            dp[i][j]=n;            if(match(ch[i],ch[j]))                dp[i][j]=min(dp[i][j],dp[i+1][j-1]);            for(int k=i;k<j;k++){                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);            }        }    }}void print(int i,int j){    if(i>j)        return ;    if(i==j){        if(ch[i]=='('||ch[i]==')')           printf("()");        else            printf("[]");        return;    }    int a=dp[i][j];    if(match(ch[i],ch[j])&&a==dp[i+1][j-1]){        printf("%c",ch[i]);        print(i+1,j-1);        printf("%c",ch[j]);        return ;    }    for(int k=i;k<j;k++){        if(a==(dp[i][k]+dp[k+1][j])){            print(i,k);            print(k+1,j);            return ;        }    }}int main(){    //freopen("d://input.txt","r",stdin);    //freopen("d://output.txt","w",stdout);    int kase;    scanf("%d",&kase);    getchar();    while(kase--){        gets(ch);        gets(ch);        n=strlen(ch);        dpMethod();        print(0,n-1);        printf("\n");        if(kase)            printf("\n");    }    return 0;}
0 0