标签:blog os io for ar 2014 amp log
题目大意:
给出一种不合法的括号序列,要求构造出一种合法的序列,使得填充的括号最少。
思路分析:
如果只要求输出最少的匹配括号的数量,那么就是简单的区间dp
dp[i][j]表示 i - j 之间已经合法了最少添加的括号数。
转移 就是 dp[i] [j] = min (dp[i+1][j]+1 , dp[ i+ 1] [ k -1 ] + dp[k+1] [j] (i k 位置的括号匹配))
其次我们要记录路径,你发现 如果 dp [i] [j] 是由 dp [i+1] [j] 转移过来的。那么第 i 个括号是一个多余存在的。所以首先我们就把这些位置标记。输出的时候不仅输出自己还要输出与之匹配的括号。。。
然后那些是通过后面有括号与之匹配而转移过来的。我们就可以把这两个位置标记。
那么这些位置就可以直接输出自己。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
char str[205];
int dp[105][105];
int pre[105][105];
int mk[105];
void mark(int pos,int n)
{
if(pos>=n)return;
if(pre[pos][n]==-1)
{
mark(pos+1,n);
}
else
{
mk[pos]=1;
mk[pre[pos][n]]=1;
mark(pos+1,pre[pos][n]-1);
mark(pre[pos][n],n);
}
}
int main()
{
scanf("%s",str+1);
int n=strlen(str+1);
memset(dp,0,sizeof dp);
memset(mk,0,sizeof mk);
memset(pre,-1,sizeof pre);
for(int i=1; i<=n; i++)dp[i][i]=1;
for(int i=n-1; i>=1; i--)
{
for(int j=i+1; j<=n; j++)
{
dp[i][j]=dp[i+1][j]+1;
pre[i][j]=-1;
for(int k=i+1; k<=j; k++)
{
if(str[i]=='('&&str[k]==')' || str[i]=='['&&str[k]==']')
{
if(dp[i+1][k-1]+dp[k+1][j]<dp[i][j])
{
pre[i][j]=k;
dp[i][j]=dp[i+1][k-1]+dp[k+1][j];
}
}
}
}
}
mark(1,n);
for(int i=1; i<=n; i++)
if(mk[i]!=1)
{
if(str[i]=='(' || str[i]==')')printf("()");
else printf("[]");
}
else
{
putchar(str[i]);
}
puts("");
return 0;
}
POJ 1141 Brackets Sequence (区间dp 记录路径),布布扣,bubuko.com
POJ 1141 Brackets Sequence (区间dp 记录路径)
标签:blog os io for ar 2014 amp log
原文地址:http://blog.csdn.net/u010709592/article/details/38639037