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);來寫吧……