Uva-1626 lrj-P278 区间dp

来源:互联网 发布:vb.net 获取网页内容 编辑:程序博客网 时间:2024/06/03 18:55

题意:

给定一个由[,],(,),构成的字符串,给其添加这些括号使得其成为一个正规括号序列

1  空序列是正规括号序列

2  如果S是正规括号序列,那么[S]和(S)也是正规括号序列

3  如果A和B都是正规括号序列,则AB也是正规括号序列

题解:

dp[i][j]有2种转移的方式:

一种是最优矩阵链乘的转移式

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

一种是如果两端的括号匹配的话

if(match(i,j)) dp[i][j]=min(dp[i][j],dp[i+1][j-1]);

dp的打印方式都是通过最优解的来源找到一条路径递归打印即可

打印的时候也要注意不同的转移方式


#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;char str[110];int dp[110][110];bool match(int a,int b){    if(str[a]=='('&&str[b]==')')        return true;    if(str[a]=='['&&str[b]==']')        return true;    return false;}void print(int a,int b){    if(a>b)  return ;    if(a==b){        if(str[a]=='('||str[a]==')') printf("()");        else                         printf("[]");        return ;    }    int ans=dp[a][b];    if(match(a,b)&&ans==dp[a+1][b-1]){        printf("%c",str[a]),print(a+1,b-1),printf("%c",str[b]);        return ;    }    for(int k=a;k<b;k++){        if(ans==dp[a][k]+dp[k+1][b]){            print(a,k),print(k+1,b);            return ;        }    }}int main(){    int T;    freopen("in.txt","r",stdin);    scanf("%d",&T);    getchar();    while(T--)    {        gets(str);        gets(str);        int len=strlen(str);        for(int i=0;i<=len;i++)            dp[i+1][i]=0,dp[i][i]=1;        for(int i=len-2;i>=0;i--){            for(int j=i+1;j<len;j++){                dp[i][j]=len;                if(match(i,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]);            }        }        print(0,len-1);        str[0]='\0';        puts("");        if(T) puts("");    }    return 0;}


原创粉丝点击