3516 Exploring Pyramids 【多叉樹遍歷】
阿新 • • 發佈:2018-12-20
題目描述:給出一棵多叉樹,每個節點的任意兩個子節點都有左右之分。從根節點開始,每次儘量往左走,走不通了就回溯,把遇到的字母順次記錄下來,可以得到一個序列。給定一個序列,問有多少棵樹與之對應。
輸入:輸入包含多組資料,每組資料僅一行,即由大寫字母組成的訪問序列。序列非空且長度不超過300。
輸出:對於每組資料,輸出滿足條件的多叉樹的數目除以10^9的餘數。
解題思路:設輸入序列為s,d[i][j]為子序列s[i],s[i+1],......,s[j]對應的樹的個數,則邊界條件是d[i][i]=1,且s[i]不等於s[j]時d[i][j]=0(因為起點和終點應是同一點)。在其他情況下,設第一個分支在s[k]時回到樹根(必須有s[i]=s[k]),則這個分支對應的序列是s[i+1],......,s[k-1],方案數為d[i+1][k-1];其他分支對應的序列為s[k],.....,s[j],方案數為d[k][j]。由此可得非邊界情況時遞推關係為:d[i][j]=sum{d[i+1][k-1]*d[k][j] | i+2<=k<=j,s[i]=s[k]=s[j]}。
AC程式碼:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <queue> #include <stack> #include <vector> #include <map> #include <set> using namespace std; #define io ios::sync_with_stdio(0),cin.tie(0) #define ms(arr) memset(arr,0,sizeof(arr)) #define inf 0x3f3f3f typedef long long ll; const int mod=1000000000; const int maxn=310; char s[maxn]; int dp[maxn][maxn]; int DP(int i,int j) { if(i==j) return 1; if(s[i]!=s[j]) return 0; int& ans=dp[i][j];//&為引用符號,改變ans的同時改變d[i][j] if(ans>=0) return ans; ans=0; for(int k=i+2;k<=j;k++) { if(s[i]==s[k]) ans=(ans+(ll)DP(i+1,k-1)*(ll)DP(k,j))%mod; } return ans; } int main() { while(scanf("%s",s)==1) { memset(dp,-1,sizeof(dp)); printf("%d\n",DP(0,strlen(s)-1)); } return 0; }