Seinfeld
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 222 Accepted Submission(s): 136
Problem Description
I’m out of stories. For years I’ve been writing stories, some rather silly, just to make simple problems look difficult and complex problems look easy. But, alas, not for this one.
You’re given a non empty string made in its entirety from opening and closing braces. Your task is to find the minimum number of “operations” needed to make the string stable. The definition for being stable is as follows:
1. An empty string is stable.
2. If S is stable, then {S} is also stable.
3. If S and T are both stable, then ST (the concatenation of the two) is also stable.
All of these strings are stable: {}, {}{}, and {{}{}}; But none of these: }{, {{}{, nor {}{.
The only operation allowed on the string is to replace an opening brace with a closing brace, or visa-versa.
You’re given a non empty string made in its entirety from opening and closing braces. Your task is to find the minimum number of “operations” needed to make the string stable. The definition for being stable is as follows:
1. An empty string is stable.
2. If S is stable, then {S} is also stable.
3. If S and T are both stable, then ST (the concatenation of the two) is also stable.
All of these strings are stable: {}, {}{}, and {{}{}}; But none of these: }{, {{}{, nor {}{.
The only operation allowed on the string is to replace an opening brace with a closing brace, or visa-versa.
Input
Your program will be tested on one or more data sets. Each data set is described on a single line. The line is a non-empty string of opening and closing braces and nothing else. No string has more than 2000 braces. All sequences are of even length.
The last line of the input is made of one or more ’-’ (minus signs.)
The last line of the input is made of one or more ’-’ (minus signs.)
Output
For each test case, print the following line:
k. N
Where k is the test case number (starting at one,) and N is the minimum number of operations needed to convert the given string into a balanced one.
Note: There is a blank space before N.
k. N
Where k is the test case number (starting at one,) and N is the minimum number of operations needed to convert the given string into a balanced one.
Note: There is a blank space before N.
Sample Input
}{ {}{}{} {{{} ---
Sample Output
1. 2 2. 0 3. 1
Source
Recommend
lcy
代码:
#include<iostream>
using namespace std;
int a[2010][2010];
int s[2010];
char ss[2010];
int main()
{
int times=0;
while(1)
{
++times;
memset(ss,'/0',sizeof(ss));
memset(s,0,sizeof(s));
memset(a,10000,sizeof(a));
cin>>&ss[1];
if(ss[1]=='-')
break;
int l=0;
for(int i=1;ss[i]!='/0';++i)
{
l=i;
if(ss[i]=='}')
s[i]=-1;
else s[i]=1;
}
if(s[1]==1)
a[1][1]=0;
else a[1][1]=1;
for(int i=1;i<l;++i)
for(int j=0;j<l;++j)
{
if(a[i][j]==10000)
continue;
if(s[i+1]==1)
{
if(j-1>=0)
{
int t=a[i+1][j-1];
if(t>a[i][j]+1)
a[i+1][j-1]=a[i][j]+1;
}
if(j+1<=l)
{
int t=a[i+1][j+1];
if(t>a[i][j])
a[i+1][j+1]=a[i][j];
}
}
if(s[i+1]==-1)
{
if(j-1>=0)
{
int t=a[i+1][j-1];
if(t>a[i][j])
a[i+1][j-1]=a[i][j];
}
if(j+1<=l)
{
int t=a[i+1][j+1];
if(t>a[i][j]+1)
a[i+1][j+1]=a[i][j]+1;
}
}
}
printf("%d. %d/n",times,a[l][0]);
}
return 0;
}
using namespace std;
int a[2010][2010];
int s[2010];
char ss[2010];
int main()
{
int times=0;
while(1)
{
++times;
memset(ss,'/0',sizeof(ss));
memset(s,0,sizeof(s));
memset(a,10000,sizeof(a));
cin>>&ss[1];
if(ss[1]=='-')
break;
int l=0;
for(int i=1;ss[i]!='/0';++i)
{
l=i;
if(ss[i]=='}')
s[i]=-1;
else s[i]=1;
}
if(s[1]==1)
a[1][1]=0;
else a[1][1]=1;
for(int i=1;i<l;++i)
for(int j=0;j<l;++j)
{
if(a[i][j]==10000)
continue;
if(s[i+1]==1)
{
if(j-1>=0)
{
int t=a[i+1][j-1];
if(t>a[i][j]+1)
a[i+1][j-1]=a[i][j]+1;
}
if(j+1<=l)
{
int t=a[i+1][j+1];
if(t>a[i][j])
a[i+1][j+1]=a[i][j];
}
}
if(s[i+1]==-1)
{
if(j-1>=0)
{
int t=a[i+1][j-1];
if(t>a[i][j])
a[i+1][j-1]=a[i][j];
}
if(j+1<=l)
{
int t=a[i+1][j+1];
if(t>a[i][j]+1)
a[i+1][j+1]=a[i][j]+1;
}
}
}
printf("%d. %d/n",times,a[l][0]);
}
return 0;
}
月赛的一题,废话不多说了,此题用栈就可以O(n)解,但是ZOJ有一题和这个题类似,但是它把每个括号都付了权值,最后求最小或者最大的权值和,这样就只能有DP来解了。
这个DP 完全是自己猜想出来的,因为没有什么经验,所以仅有这点成功的经验赶快记录下来供后来回忆。
此题DP为O(n2)时间。基本思路是把括号抽象成数字1=(和-1=)
设置DP的矩阵为2维a[i][j]
i表示这个串的钱i项组成的子串 j表示当前子串有多少个(多余的积累,即前i项和为多少
根据第i+1项的值即s[i+1]的大小,可以有分两种情况讨论递推方程
当s[i+1]=1时,a[i+1][j+1]=a[i][j];(即不对"("进行变换)
a[i+1][j-1]=a[i][j]+1;(将“("进行变换,需要一步操作)
同理当s[i+1]=-1时,a[i+1][j-1]=a[i][j];(即不对")"进行变换)
a[i+1][j+1]=a[i][j]+1;(将“)"进行变换,需要一步操作)
由于只要知道a[i][x]就可以知道a[i][x+1]和a[i][x-1],所以确定计算顺序为从a[1][1]->a[2][2]->a[2][0]->a[3][1]->a[3][3]...
即以列优先的顺序进行计算,通过比较确定每个a[i][j]的最小值,最后a[l][0]即为答案。
注意i和j不能越过边界。
当前对DP的认识:主要是自低向上的顺序,a[i][j][k]...保存要进行比较求得的当前子问题的临时解或最优解。其中a的维度决定DP的时间效率。各个维度表示不同的信息。比如此题i表示对原问题的一种划分,a[i]表示原串的前i个元素组成的子串,即按照线性进行划分。也可能这个划分不是线性的,比如LCS问题中,将原问题划分为2维的子问题,即由两个不同长度串决定不同的子问题。具体的划分方法由问题本身确定。a其他的维度可以是当前子问题的某种参数,某种特性,这种特性影响着最优解的形成,所以DP时需要将它包括在内考虑。比如此题中j表示当前字串和为多少,此和影响着是否最后能形成最优解。当然这个维度也是可能不止一个。