【发布时间】:2015-11-06 12:10:35
【问题描述】:
所以,我试图解决以下问题:http://www.spoj.com/problems/MREPLBRC/en/
正则括号序列是一串仅由左括号和右括号组成的字符串,并且满足以下条件:
• 空字符串是常规括号序列。
• 如果 A 是正则括号 0 序列,则 (A)、[A] 和 {A} 也是正则括号序列。
• 如果 A 和 B 是正则括号序列,则 AB 也是正则括号序列。
例如,序列 [({})]、{} i {}[{}] 是正则序列,但序列 [({{([, } 和 [{}])([{}]不是。
Ivica 找到了一个看起来可能是常规括号序列的字符串。一些字符已经被弄脏并且难以辨认,并且可能是任何字符。
编写一个程序,计算字符串中难以辨认的字符有多少种方式可以被括号替换,从而得到一个规则的括号序列。这个数字可能很大,所以只输出它的最后 5 位。
输入
第一行包含一个偶数 N (2
第二行包含字符串。难以辨认的字符由“?”表示字符。
输出
输出字符串可以读取的常规括号序列的数量。
经过深思熟虑,我无法真正为此形成解决方案,因此我试图寻找解决方案。我在这里找到它:http://ruhinraihan.blogspot.in/2012/08/spoj-4038-counting-way-of-bracket.html
下面是代码:
#include<iostream>
#include<list>
#include<string>
#include<cstring>
#include<sstream>
#include<cctype>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<fstream>
#include<cstdlib>
#include<vector>
#include<map>
#include<utility>
#include<iomanip>
#include<queue>
using namespace std;
#define INF (1<<29)
#define SET(a) memset(a,-1,sizeof(a))
#define ALL(a) a.begin(),a.end()
#define CLR(a) memset(a,0,sizeof(a))
#define FILL(a,v) memset(a,v,sizeof(a))
#define PB push_back
#define FOR(i,n) for(int i = 0;i<n;i++)
#define PI acos(-1.0)
#define EPS 1e-9
#define MP(a,b) make_pair(a,b)
#define READ(f) freopen(f, "r", stdin)
#define WRITE(f) freopen(f, "w", stdout)
#define LL long long
#define MOD 100000
bool moduloUsed;
LL memo[200+10][200+10];
string s;
LL func(int left, int right)
{
int i, valid;
if(left>right) return 1;
if(memo[left][right]!=-1) return memo[left][right];
LL ret=0;
for(i=left+1;i<=right;i+=2)
{
if(s[left]=='(' && s[i]==')') valid=1;
else if(s[left]=='{' && s[i]=='}') valid=1;
else if(s[left]=='[' && s[i]==']') valid=1;
else if(s[left]=='?' && s[i]==')') valid=1;
else if(s[left]=='?' && s[i]=='}') valid=1;
else if(s[left]=='?' && s[i]==']') valid=1;
else if(s[left]=='(' && s[i]=='?') valid=1;
else if(s[left]=='{' && s[i]=='?') valid=1;
else if(s[left]=='[' && s[i]=='?') valid=1;
else if(s[left]=='?' && s[i]=='?') valid=3;
else valid=0;
ret+=valid*func(left+1,i-1)*func(i+1,right);
if(ret>MOD)
{
moduloUsed=true;
ret%=MOD;
}
}
return memo[left][right]=ret;
}
int main()
{
LL ans,length;
while(cin>>length>>s)
{
SET(memo);
ans=func(0,length-1);
if(!moduloUsed)
cout<<ans<<endl;
else
printf("%05lld\n",ans);
}
return 0;
}
我想知道,函数fun 中到底发生了什么。我知道它正在遍历输入字符串,并检查平衡括号条件的可能组合,但是,func(left+1,i-1)*func(i+1,right),这两个递归调用代表什么?请帮我。
【问题讨论】:
-
但是您是否也知道在 C 和 C++ 中有 switch/case 语句?
-
@decltype_auto,你为什么在这里询问开关/案例?可以用另一种方式重写这段代码(使用
switch),但这无助于Harry 理解这段代码的逻辑。 -
@decltype_auto,无意冒犯,但如果您停止向其他人炫耀您的知识渊博并帮助我,这对我会有很大帮助。正是因为像你这样的人,很多初学者常常因为你试图表现出你惊人的幽默而无法学习,相信我,这根本没有那么神奇。
-
@decltype_auto,我愿意,但是,与其说对任何人都没有帮助的话,不如让你的答案(这有助于 OP)说出我的感受。不要说它会提高可读性,而是写一个答案来表明它会提高可读性。如果是这样,我很乐意接受您的回答。
-
@decltype_auto,天哪。这太神奇了。您自己建议代码需要重组,现在您自己说 SO 不是代码编写服务。至少看看我问的问题。我从来没有要求你为我写代码。我只是请你帮我解释一下逻辑。至少在一件事上保持头脑清醒。
标签: c++ algorithm recursion dynamic-programming