所以,我试图解决以下问题:http://www.spoj.com/problems/MREPLBRC/en/
常规括号序列是一串字符,仅包含左括号和右括号,并满足以下条件:
•空字符串是常规括号序列。
•如果A是常规的bracket0序列,则(A),[A]和{A}也是常规括号序列。
•如果A和B是常规括号序列,则AB也是常规括号序列。
例如,序列[({})],{} i {} [{}]是常规的,但序列[({{([,}和[{}])([{}]是不
Ivica找到了一个看起来像是常规括号序列的字符串。有些角色变得污迹化,难以辨认,可能是任何角色。
编写一个程序,计算字符串中的字符串可以被括号替换的方式,以便结果是常规括号序列。这个数字可能非常大,因此只输出最后5位数字。
输入
第一行包含偶数整数N(2 <= N <= 200),即字符串的长度。
第二行包含字符串。难以理解的字符由&#39;?&#39;表示。字符。
输出
输出字符串可以读取的常规括号序列的数量。
经过多次思考,我无法真正形成解决方案,因此,我试图寻找解决方案。我在这里找到了它: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)
,这两个递归调用代表什么?请帮我。
答案 0 :(得分:1)
基本上,通过将任何open + close括号对的所有有效组合相乘来达到答案。 long winded if语句是递归函数的停止条件,因为任何一对都可以有0,1或3个有效组合。抛出你的递归调用实际上(与for循环结合)扫描整个字符串以获得括号对。如果说这个字符串是对称的,那就更简单了:fun(left + 1, right -1)