【NK月赛 JUNE2012 E】做错的作业
Time Limit:10000MS Memory Limit:65536K
Total Submit:94 Accepted:54
Case Time Limit:1000MS
Description
小影(人名) 的数学作业错误百出.
老师:“你作业的表达式里面只有n个括号,怎么就写错了这么多?”
“n那么大,都到300了。”
老师:“那第一个小题只有一个括号你都写错了,这怎么解释?你看,你就写了一个‘(’,明显漏掉了一个‘)’吧?”
“这……”小影似乎很清楚的记得自己是写的“()”,可是现在怎么只剩下“(”了呢?
老师:“你看别人某某,写的多好?十道题都做对了。这样吧,我不看你的计算结果了,只看你的括号匹配得正不正确,你今天之内把你的括号修改正确就可以了……”
“嘿嘿……我把括号全部划掉不就全对了?”小影阴险地想。
老师:“……不过有一个条件:你只能添加括号而不能把括号划掉,并且你只能添加最少数量的括号。”
“天呐!”小影瘫倒了,要知道十个题目里面只有第一题很简单,其他的题目括号数目是巨多的。
看来,只能请善良的你帮帮小影了。
Input
只有一行,为一个长度为n的字符串,代表小影作业中写的括号。其中有4类括号“()”“[]”“<>”“{}”,“(”和“)”匹配,“[”和“]”匹配,“<”和“>”匹配,“{”和“}”匹配,左括号必须在左,右括号必须在右,其他组合是不匹配的。两个匹配的括号中间可以夹有其他已经匹配的括号。如“([<{}>])(){}”就是匹配的。
Output
一个整数,为小影最少需要添加的括号数目。
Sample Input
([(]{})(<>))
Sample Output
2
Hint
对于30%的数据,n<=50;
对于100%的数据,n<=300
Source
命题:Chyy(08级24班);审题:Cauchy(08级5班);数据:Chyy。
我们用f[i][j]表示从第i个点开始的j个位置匹配所需的最小括号数
其中min{f[i][k-1]+f[k+i][j-k-1]} 是表示i后第j个括号和i后第k个括号匹配,1=<k<=j-1
为了方便讨论,我们在输入的时候应该将输入的括号换成数字,从而容易判断括号是否匹配
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int inf=2e9;
char c[305];
int n,f[305][305],s[305];
int main(){
scanf("%s",c+1);
int i,j,k;
n=strlen(c+1);
for(i=1;i<=n;i++){
if(c[i]=='(')s[i]=1;
if(c[i]==')')s[i]=9;
if(c[i]=='{')s[i]=2;
if(c[i]=='}')s[i]=8;
if(c[i]=='<')s[i]=3;
if(c[i]=='>')s[i]=7;
if(c[i]=='[')s[i]=4;
if(c[i]==']')s[i]=6;
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
f[i][j]=inf;
for(i=1;i<=n;i++)
f[i][1]=1;
for(j=1;j<=n;j++)
for(i=1;i<=n-j+1;i++){
f[i][j]=min(f[i][j],f[i][j-1]+1);
for(k=1;k<=j-1;k++)
if(s[i+k-1]+s[i+j-1]==10&&s[i+k-1]<s[i+j-1])
f[i][j]=min(f[i][j],f[i][k-1]+f[k+i][j-k-1]);
}
cout<<f[1][n];
}