POJ1141 Brackets Sequence

来源:互联网 发布:q宠大乐斗门派数据详解 编辑:程序博客网 时间:2024/06/07 14:45

       大致的意思是将一个非规范的序列转化成规范的序列,如 ([(],这是一个非规范的序列,处理之后要求输出规范的序列:()[()],要求就是添加最少的括号。

    黑书上通过这题来介绍选择DP的原因之一:递归。

    因为序列Si····Sj,可以分成:Si···Sk,Sk+1···Sj,只要d(i,k)+d(k+1,j)最小,则d(i,j)=min(d(i,j),d(i,k)+d(k+1,j));当然还有一种特殊的情况:SiSj=()或SiSj=[],对于这种情况,d(i,j)=min(d(i,j),d(i+1,j-1))。显而易见,是可以用递归解决的,但是中间产生了大量需要重复计算的状态,为了减少计算,我们将这些状态存储起来,用空间来换取时间,因此转化为了DP。

#include <stdio.h>#include <string.h>#define INF_MAX 300#define min(a,b) ((a<b)?(a):(b))int num[110][110];int p[110][110];char input[110];void output(int s, int e);int main(){int len;int i,j,k;int temp;//freopen("test.txt","r",stdin);scanf("%s",input);len=strlen(input);memset(num,-1,sizeof(num));memset(p,-1,sizeof(p));for(i=0;i<len;i++){num[i][i]=1;num[i+1][i]=0;}for(i=len-2;i>=0;i--)for(j=i+1;j<len;j++){num[i][j]=INF_MAX;if((input[i]=='(' && input[j]==')') || (input[i]=='[' && input[j]==']')){num[i][j]=min(num[i][j],num[i+1][j-1]);}for(k=i;k<j;k++){temp=num[i][k]+num[k+1][j];if(temp<num[i][j] || num[i][j]==-1){num[i][j]=temp;p[i][j]=k;}}} output(0,len-1); putchar('\n');  return 0;}void output(int s, int e){if (s > e)return;if (s == e){if (input[s] =='('|| input[s] ==')')printf("()");elseprintf("[]");return;}if (p[s][e] ==-1){putchar(input[s]);output(s +1, e -1);putchar(input[e]);return;}output(s, p[s][e]);output(p[s][e] +1, e);}

需要注意的是i和j的循环顺序,当i=0时,需要i=1,i=2,i=3等子序列的状态,因此i从后往前遍历。output程序是直接复制网上的,不过网上output几乎都一模一样,不知道谁才是原创····

原创粉丝点击