题意:给出一棵多叉树,每个结点的任意两个子节点都有左右之分。从根节点开始,每次尽量往左走,走不通就回溯,把遇到的字母顺序记录下来,可以得到一个序列。给定一个序列,问有几种满足的多叉树。
思路:
1 设输入的序列为S,dp[i][j]为子序列Si,Si+1...Sj对应的树的个数,则边界条件是dp[i][i] = 1,且Si不等于Sj时dp[i][j] = 0。
2 这样在非边界情况下,Si = Sj递推的关系为dp[i][j] = sum{dp[i+1][k-1]*dp[k][j]} i+2 <= k <= j。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long int64; const int MAXN = 310; const int MOD = 1e9; char str[MAXN]; int64 ans[MAXN][MAXN]; int64 solve(int i , int j){ if(i == j) return 1; if(str[i] != str[j]) return 0; if(ans[i][j] >= 0) return ans[i][j]; ans[i][j] = 0; for(int k = i+2 ; k <= j ; k++) ans[i][j] += (solve(i+1 , k-1)*solve(k , j))%MOD; return ans[i][j]; } int main(){ while(scanf("%s" , str) != EOF){ memset(ans , -1 , sizeof(ans)); printf("%lld\n" , solve(0 , strlen(str)-1)); } return 0; }