您的位置:首页 > 产品设计 > UI/UE

poj 1141 Brackets Sequence (DP+构造)

2013-11-06 10:45 337 查看
题意:给你一个含有中括号和小括号的序列,让你使用最少的括号,使这个括号序列合法。

思路:定义状态:dp[a][b]表示a-b区间中使其合法最少使用的括号数。初始化时: dp[x][x]=1; 

状态转移:if(最外层的两个点a,b为一个完整的括号对)    dp[a][b]=dp[a-1][b+1];

    dp[a][b]=min(dp[a][b],dp[a][k],dp[k+1][b]),(a=<k<b)

从状态转移可以看出,dp[a][b]是从b-a为1开始向上转移的,所以递推时,循环的是他们之间的间隔距。最后只要在转移过程中记录下来是从什么地方转移的即可,最后DFS输出序列。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#define inf 0x3f3f3f
using namespace std;
const int maxn=222;
int dp[maxn][maxn];
char ch[maxn];
int mark[maxn][maxn];
void work()
{
int len=strlen(ch);
memset(mark,-1,sizeof(mark));
for(int i=0;i<len;i++)
{
dp[i][i]=1;
}
for(int i=1;i<len;i++)
{
for(int j=0;j<len-i;j++)
{
int tt=j+i;
dp[j][tt]=inf;
if(((ch[j]=='(')&&(ch[tt]==')'))||((ch[j]=='[')&&(ch[tt]==']')))
{
dp[j][tt]=dp[j+1][tt-1];
mark[j][tt]=-1;
}
for(int k=j;k<tt;k++)
{
if(dp[j][tt]>dp[j][k]+dp[k+1][tt])
{
dp[j][tt]=dp[j][k]+dp[k+1][tt];
mark[j][tt]=k;
}
}
}
}
}
void dfs(int a,int b)
{
if(a>b)
{
return;
}
if(a==b)
{
if(ch[a]=='('||ch[a]==')') printf("()");
if(ch[a]=='['||ch[a]==']') printf("[]");
return ;
}
if(mark[a][b]==-1)
{
printf("%c",ch[a]);
dfs(a+1,b-1);
printf("%c",ch[b]);
}
else
{
dfs(a,mark[a][b]);
dfs(mark[a][b]+1,b);
}
}
int main()
{
// freopen("in.txt","r",stdin);
while(gets(ch))
{
work();
int len=strlen(ch);
dfs(0,len-1);
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp