POJ 1411:Brackets Sequence 区间DP

Brackets Sequence

题目链接:

http://poj.org/problem?id=1141

题意:

给出一个只由'('、')'、'['、']'构成的字符串,字符间可以匹配,左边的 '(' 可以与右边的 ')' 匹配,左边的 '[' 可以与右边的 ']' 匹配

两种匹配不能交叉,可以包含,如 [(])只算2个匹配而[()]算四个匹配,求最少加上几个字符可以使原串所有的字符都匹配,输出匹配后的字符串。

 

题解:

设dp[i][j]为将区间[i,j]补全的最小步数,to[i][j]为dp[i][j]取最小值时与 j 匹配的点,可以知道

    当区间[i,j-1]内没有可以与 j 匹配的点时,dp[i][j]=dp[i][j-1]+1,to[i][j]=j (j与自己匹配,额外加点)

    当区间[i,j-1]内有点k可以与j匹配时,dp[i][j]=dp[i][k-1]+dp[k+1][j-1],to[i][j]=k

然后深搜找路径,将与自己匹配的点补全就行了,注意题目会有直接输入回车要输出回车的情况。

              

代码

#include<stdio.h>
#include<string.h>
const int N=101;
char s[N];
bool ans[N];
int dp[N][N],to[N][N];
int mmin(int x,int y)
{
  return x<y?x:y;
}
char Get_c(char c)
{
  if(c==')')return '(';
  if(c=='(')return ')';
  if(c=='[')return ']';
  if(c==']')return '[';
}
void Dfs(int x,int y)
{
  if(x>y)return;
  if(to[x][y]==y)
  {
    ans[y]=true;
    Dfs(x,y-1);
    return ;
  }
  if(to[x][y]==x)
  {
    Dfs(x+1,y-1);
    return ;
  }
  Dfs(x,to[x][y]-1);
  Dfs(to[x][y]+1,y-1);
}
void solve()
{
  memset(dp,0,sizeof(dp));
  while(gets(s+1))
  {
    s[0]='?';
    int t=strlen(s)-1;
    for(int i=1;i<=t;++i)
    {
      dp[i][i]=1;
      to[i][i]=i;
      ans[i]=false;
    }
    for(int len=1;len<t;++len)
    {
      for(int i=1;i+len<=t;++i)
      {
        int j=i+len;
        char c=Get_c(s[j]);
        dp[i][j]=dp[i][j-1]+1;
        to[i][j]=j;
        if(c==']'||c==')')continue;
        for(int k=i;k<j;++k)
        if(s[k]==c&&dp[i][k-1]+dp[k+1][j-1]<dp[i][j])
        {
          dp[i][j]=dp[i][k-1]+dp[k+1][j-1];
          to[i][j]=k;
        }
      }
    }
    Dfs(1,t);
    for(int i=1;i<=t;++i)
    if(!ans[i])printf("%c",s[i]);
    else
    {
      if(s[i]=='('||s[i]=='[')printf("%c%c",s[i],Get_c(s[i]));
      else printf("%c%c",Get_c(s[i]),s[i]);
    }
    printf("\n");
  }
}
int main()
{
  solve();
  return 0;
}

posted @ 2016-08-08 15:35  kiuhghcsc  阅读(162)  评论(0编辑  收藏  举报