Gym 101334E Exploring Pyramids(dp+乘法原理)
http://codeforces.com/gym/101334
题意:
给出一棵多叉树,每个结点的任意两个子节点都有左右之分。从根结点开始,每次尽量往左走,走不通了就回溯,把遇到的字母顺次记录下来,可以得到一个序列。
思路:
d【i】【j】表示i~j的序列所对应的子树。
边界条件就是d【i】【i】=1。
每次可以分为两个分支:d【i+1】【k-1】和d【k】【j】。
递归求解。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,int> pll; 14 const int INF=0x3f3f3f3f3f; 15 const int maxn=300+5; 16 17 const int MOD=1000000000; 18 19 char str[maxn]; 20 ll d[maxn][maxn]; 21 22 ll dp(int i,int j) 23 { 24 if(d[i][j]!=-1) return d[i][j]; 25 if(i==j) return d[i][j]=1; 26 if(str[i]!=str[j]) return d[i][j]=0; 27 28 d[i][j]=0; 29 30 for(int k=i+2;k<=j;k++) 31 { 32 if(str[i]==str[k] && str[k]==str[j]) 33 d[i][j]=(d[i][j]+dp(i+1,k-1)*dp(k,j))%MOD; 34 } 35 return d[i][j]; 36 } 37 38 int main() 39 { 40 freopen("exploring.in","r",stdin); 41 freopen("exploring.out","w",stdout); 42 //freopen("D:\\input.txt","r",stdin); 43 while(~scanf("%s",&str)) 44 { 45 memset(d,-1,sizeof(d)); 46 int len=strlen(str); 47 printf("%lld\n",dp(0,len-1)); 48 } 49 }