Exploring Pyramids UVALive - 3516 多叉樹遍歷


給出一棵多叉樹,每個結點的任意兩個子結點都有左右之分。從根結點開始,每次儘量往左走,走不通了就回溯,把遇到的字母順次記錄下來,可以得到一個序列。如圖2-6所示的5 個圖的序列均爲ABABABA 。給定一個序列,問有多少棵樹與之對應。

【輸入格式】
輸入包含多組數據。每組數據僅一行,即由大寫字母組成的訪問序列。序列非空,且長度不超過300 。輸入結束標誌爲文件結束符(EOF) 。
【輸出格式】
對於每組數據,輸出滿足條件的多叉樹的數目除以10^9 的餘數。
【分析】
設輸入序列爲S,d(i,j)爲子序列Si,Si+1,.....Sj與對應的樹的個數,則邊界條件是d(i,i)=1,且Si 不等於Sj時d(i,j)=0( 因爲起點和終點應是同一點)。在其他情況下,設第一個分支在Sk 時回到樹根(必須有Si = Sk) ,則這個分支對應的序列是Si+1,...Sk-1,方案數爲d(i+1,k-1);
其他分支對應的訪問序列爲Sk,...Sj,方案數爲d(kJ) 。這樣,在非邊界情況,遞推關係爲
,如圖2-7 所示。 

#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 300 + 10;
const int MOD = 1000000000;
typedef long long LL;

char S[maxn];
int d[maxn][maxn];

int dp(int i, int j) {
  int& ans = d[i][j];
  if(ans >= 0) return ans;
  if(i == j) return ans = 1;
  if(S[i] != S[j]) return ans = 0;
  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(d, -1, sizeof(d));
    printf("%d\n", dp(0, strlen(S)-1));
  }
  return 0;
}

 

發佈了499 篇原創文章 · 獲贊 598 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章