/**
* 挺不错的DP题,黑书dp专题第一例。
* 输出搞了近一个小时的输出,结果发现不是输出的问题,
* 是在处理pos和dp数组的时候更新dp用的是dp[.]=min(dp[.],dp[..])的形式。
* 忽略了pos[i][j]的更新应该在满足dp[..] < dp[.]的时候才更新的
* 所以建议还是少用min去更新,避免遗漏还是if(dp[.]>dp[..]){...}的形式更新
* 至于如何dp,黑书上讲的也挺详细的,dp[i][j]表示下标从i到j的子串变成合法形式
* 所添加的最少括号数。 这样在递推求dp的过程就是区间长度(i-j+1)从1一直到len-1去更新
* 当前最优子结构dp[i][j]
* 状态转移方程就是: dp[i][j] = min(dp[i][j], dp[i][z]+dp[z+1][j]) z在i到j-1范围枚举
* 其余要注意的是,初始化的时候dp[i][i] = 1; dp[i][i+1] = 0;
* 为什么dp[i][i+1] 要初始化为0?
* 因为: 当str[i]和str[j]能正常配对且j=i+1的时候, dp[i][j] = dp[i+1][j-1];
* 这个时候因为dp[i][j]已经是合法的,所以值应该是0,所以dp[i][i+1]都要初始化为0
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#define DEBUG 0
#define INF 0x1fffffff
#define MAXN 105
typedef long long LL;
using namespace std;
int dp[MAXN][MAXN], pos[MAXN][MAXN];
int len;
char str[MAXN];
void print(int l, int r)
{
if(l > r) return ;
if(l == r) {
if(str[l] == '(' || str[l] == ')')
printf("()");
else
printf("[]");
return ;
}
if(pos[l][r] == -1) {
printf("%c", str[l]);
print(l+1, r-1);
printf("%c", str[r]);
return ;
}
print(l, pos[l][r]);
print(pos[l][r]+1, r);
}
void dpf()
{
for(int i = 0; i <= len; i ++) {
dp[i][i] = 1;
dp[i][i+1] = 0;
}
for(int k = 1; k < len; k ++)
{
for(int i = 1; i <= len - k; i ++) {
int j = i + k;
dp[i][j] = INF;
pos[i][j] = -1;
if(str[i] == '(' && str[j] == ')' ||
str[i] == '[' && str[j] == ']' ) {
dp[i][j] = dp[i+1][j-1];
}
for(int z = i; z < j; z ++) {
if(dp[i][j] > dp[i][z] + dp[z+1][j]) {
dp[i][j] = dp[i][z] + dp[z+1][j];
pos[i][j] = z;
}
}
}
}
}
int main()
{
scanf("%s", str+1);
len = strlen(str+1);
dpf();
print(1, len);
puts("");
return 0;
}
POJ 1141 Brackets Sequence (DP+路径处理)
最新推荐文章于 2021-05-25 11:51:06 发布