nkoj 1507
水水的动归题一道。。。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int inf=2e9;
char str[305];
int s[305],f[305][305];
//f[i][j]表示将i到j变成合法串需要添加几个括号
int main(){
int i,n,j;
scanf("%s",str+1);
n=strlen(str+1);
for(i=1;i<=n;i++){ //将括号转化为数字,存在数组S里
if(str[i]=='(')s[i]=1;
else if(str[i]=='[')s[i]=2;
else if(str[i]=='<')s[i]=3;
else if(str[i]=='{')s[i]=4;
else if(str[i]==')')s[i]=5;
else if(str[i]==']')s[i]=6;
else if(str[i]=='>')s[i]=7;
else if(str[i]=='}')s[i]=8;
}
for(i=1;i<=n;i++)f[i][i]=1; //初值,单个括号需要加一个括号
for(i=n;i>0;i--) //逆序
for(j=i+1;j<=n;j++){
int minn=inf;
if(s[j]-s[i]==4) //恰好配对
minn=min(minn,f[i+1][j-1]);
for(int k=i;k<j;k++) //枚举从i到j中任意点断开是否更优
minn=min(minn,f[i][k]+f[k+1][j]);
f[i][j]=minn;
}
printf("%d",f[1][n]);
}
有一个小细节,如果i和j恰好配对,也要继续讨论,否则例如‘【】【】’就会被理解成‘】【’而需要添加两个括号。