http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1463
题目大意:
给出括号序列的递归定义:
1、空序列
2、如果S是括号序列,那么(S) [S]也是
3、如果A和B是括号序列,那么AB也是
给出一个串,添加最少的()[]使串变为括号序列,输出结果。
解题思路:
一直不记得在哪里做过,不过只需要输出添加的括号数……
比较经典的DP模型,记输入串为str:
f[i][j]为str[i..j]要成为括号序列需要添加的括号数,初始化f[i][i]=1,之后先令f[i][j]=(str[i],str[j]配对成括号)?f[i+1][j-1]:maxint,之后f[i][j]=min(f[i][j], f[i][k]+f[k+1][j])
由于要输出最终括号序列,记录DP过程中的括号添加情况,用a[i][j]记录。i!=j时,a[i][j]=-2表示str[i],str[j]配对成括号,否则a[i][j]=k表示f[i][j]=f[i][k]+f[k+1][j].
使用a[i][j]数组递归输出括号序列,注意i==j时直接加括号,i>j时return;
源代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 300
const int maxint=1<<29;
char str[maxn];
int len;
int a[maxn][maxn]; //括号添加位置
int f[maxn][maxn]; //添加括号数
void dfs(int x, int y)
{
if (x>y) return;
if (x==y)
{
if (str[x]=='(' || str[x]==')') printf("()");
if (str[x]=='[' || str[x]==']') printf("[]");
}
else if (a[x][y]==-2)
{
printf("%c", str[x]);
dfs(x+1, y-1);
printf("%c", str[y]);
}
else{
dfs(x, a[x][y]);
dfs(a[x][y]+1, y);
}
}
int main()
{
int cs;
scanf("%d", &cs);
gets(str);
for (int css=1; css<=cs; css++)
{
if (css>1) printf("\n");
len=0;
gets(str);
gets(str);
len=strlen(str);
for (int i=0; i<len; i++)
{
f[i][i]=1;
a[i][i]=i;
}
for (int p=1; p<=len; p++)
for (int i=0; i<len-p; i++)
{
int j=i+p;
if ((str[i]=='(' && str[j]==')') || (str[i]=='[' && str[j]==']'))
{
f[i][j]=(p>1)?f[i+1][j-1]:0;
a[i][j]=-2; //不加括号
}
else
f[i][j]=maxint;
for (int k=i, t; k<=j; k++)
if ((t=f[i][k]+f[k+1][j])<f[i][j])
{
f[i][j]=t;
a[i][j]=k;
}
}
dfs(0, len-1);
printf("\n");
}
return 0;
}
解题心得:
这道题输入很猥琐呃,WA了很多次。
最后看了POJ上的Discuss,要用gets一行一行读入,否则会读不清楚……
以后这种莫名其妙的读入还是用freopen("test.txt", "r", stdin);来写吧……