http://acm.hust.edu.cn/vjudge/contest/view.action?cid=105116#problem/E
题意:添加最少的括号,让每个括号都能匹配并输出
分析:dp[i][j]表示第i个到第j个需要添加的最少的括号,pos[i][j] = k;表示i到j间第k个需要加括号;
如果str[i]和str[j]匹配,那么dp[i][j] = max(dp[i + 1][j - 1], dp[i][j]);
如果str[i]和str[j]不匹配,那么dp[i][j] = max(dp[i][j], dp[i][k]+dp[k + 1][j]); i<= k < j;之前想过k为什么不能等于j,
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int MAX = ;
const int INF = 0x3f3f3f3f;
int dp[MAX][MAX],pos[MAX][MAX];
char str[MAX];
int n;
void DP()
{
n = strlen(str); memset(dp, , sizeof(dp));
for(int i = ; i < n; i++)
dp[i][i] = ;
for(int p = ; p < n; p++)
{
for(int i = ; i < n; i++)
{
int j = i + p;
if(j >= n)
break;
dp[i][j] = INF;
if( (str[i] == '(' && str[j] == ')') || ( str[i] == '[' && str[j] == ']' ) )
{
if(dp[i][j] > dp[i + ][j - ])
dp[i][j] = dp[i + ][j - ];
}
pos[i][j] = -;
for(int k = i; k < j; k++)
{
int temp = dp[i][k] + dp[k + ][j];
if(temp < dp[i][j])
{
dp[i][j] = temp;
pos[i][j] = k;
}
}
}
}
}
void Print(int beg, int End)
{
if(beg > End)
return;
if(beg == End)
{
if(str[beg] == '(' || str[beg] == ')')
printf("()");
if(str[beg] == '[' || str[beg] == ']')
printf("[]");
}
else
{
if(pos[beg][End] == -)
{
printf("%c", str[beg]);
Print(beg + , End - );
printf("%c", str[End]);
}
else
{
Print(beg, pos[beg][End]);
Print(pos[beg][End] + , End);
}
}
}
int main()
{
int t;
scanf("%d", &t);
getchar();
getchar();
for(int i = ; i < t; i++)
{
gets(str);
DP();
Print(, n - );
printf("\n");
if(i < t - )
printf("\n");
getchar();
} return ;
}