题意:
括号序列由(),[],{},组成,例如(([{}]))()是合法的,而(}{)和(}(}都是不合法的。如果一个序列不合法,编写一个程序,求添加最少括号数,使得这个序列变成合法的。例如(}(}最少需要添加4个括号变成合法的,既变为(){}(){}。
思路:经典的区间dp问题,定义f[l][r]为将c[l]至c[r]变为合法的最少括号数。
则当c[l] == c[r]时,f[l][r] = f[l + 1][r - 1]
当c[l] != c[r]时, f[l][r] = min(f[l + 1][r], f[l][r - 1]) + 1;
再考虑将l~r分成两个区间的决策 f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r])
具体细节看代码:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 110;
char c[N];
int n, f[N][N];
bool cheak(char a, char b)
{
if(a == '[' && b == ']') return true;
if(a == '(' && b == ')') return true;
if(a == '{' && b == '}') return true;
return false;
}
int main()
{
scanf("%s", c);
n = strlen(c);
for(int len = 1; len <= n; len ++ )
for(int l = 0; l + len - 1 < n; l ++ )
{
int r = l + len - 1;
if(len == 1) f[l][r] = 1; //初始化
else
{
f[l][r] = 0x3f3f3f3f;
if(cheak(c[l], c[r])) f[l][r] = f[l + 1][r - 1];
// else f[l][r] = min(f[l + 1][r] + 1, f[l][r - 1] + 1); 该决策被下面循环枚举所包含,所以可以注释掉
for(int k = l; k < r; k ++ )
f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r]);
}
}
cout << f[0][n - 1] << endl;
return 0;
}