poj 1141 Brackets Sequence

/*
dp 如果是统计最少加多少个括号 就是区间dp
   如果区间两头是匹配的 就可以用 i+1 j-1 更新
 然而这题要输出方案 
 就类似记路径 记背包选哪几个一样
 维护一个bj表示 i到j的最优解是由 分成哪两份转移来的 
 如果无法分 就是-1 
 最后递归搞输出方案 递归终点就是需要改变的点  
*/
#include<iostream>
#include<cstdio>
#include<cstring> 
using namespace std;
int l,f[110][110],bj[110][110],a[110];
char s[110];
void Dfs(int x,int y)
{
    if(x>y)return;
    if(x==y)a[x]=1;
    if(bj[x][y]==-1)Dfs(x+1,y-1);
    else if(bj[x][y]>0)
      {
          Dfs(x,bj[x][y]);
          Dfs(bj[x][y]+1,y);
      }
}
int main()
{
    scanf("%s",s+1);
    l=strlen(s+1);
    if(l==0)//特判特判  
      {
          printf("\n");
          return 0;
      }
    for(int i=1;i<=l;i++)
      f[i][i]=1;
    for(int i=l-1;i>=1;i--)
      for(int j=i+1;j<=l;j++)
        {
            f[i][j]=99999999;
            if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']'))
              if(f[i][j]>f[i+1][j-1])
              {
                f[i][j]=f[i+1][j-1];
                bj[i][j]=-1;
              }
            for(int k=i;k<j;k++)
              if(f[i][k]+f[k+1][j]<f[i][j])
                {
                  f[i][j]=f[i][k]+f[k+1][j];
                  bj[i][j]=k;
                }
        }
    Dfs(1,l);
    for(int i=1;i<=l;i++)
      if(a[i])
        {
          if(s[i]=='('||s[i]==')')printf("()");
          else printf("[]");
        }
      else printf("%c",s[i]);
    return 0;
}

 

posted @ 2016-05-15 18:29  一入OI深似海  阅读(139)  评论(0编辑  收藏  举报