LA 3516 (计数 DP) Exploring Pyramids

设d(i, j)为连续子序列[i, j]构成数的个数,因为遍历从根节点出发最终要回溯到根节点,所以边界情况是:d(i, i) = 1; 如果s[i] != s[j], d(i, j) = 0

假设第一个分支在Sk回到根节点,方案数为d(i+1, k-1)

其他分支访问从Sk到Sj,方案数为d(k, j)

根据乘法原理,d(i, j) = sum{d(i+1, k-1), d(k, j), i+2≤k≤j 且 Si = Sk = Sj}

 1 #include <bits/stdc++.h>

 2 using namespace std;

 3 

 4 typedef long long LL;

 5 

 6 const int maxn = 300 + 10;

 7 const int MOD = 1000000000;

 8 

 9 char s[maxn];

10 int d[maxn][maxn];

11 

12 int dp(int i, int j)

13 {

14     if(i == j) return 1;

15     if(s[i] != s[j]) return 0;

16     int& ans = d[i][j];

17     if(ans >= 0) return ans;

18 

19     ans = 0;

20     for(int k = i + 2; k <= j; k++) if(s[i] == s[k])

21         ans = (ans + (LL)dp(i+1, k-1) * (LL)dp(k, j)) % MOD;

22     return ans;

23 }

24 

25 int main()

26 {

27     while(scanf("%s", s) == 1)

28     {

29         memset(d, -1, sizeof(d));

30         printf("%d\n", dp(0, strlen(s) - 1));

31     }

32 

33     return 0;

34 }
代码君

 

你可能感兴趣的:(exp)