《算法竞赛-训练指南》第二章-2.4-LA 3516

来源:互联网 发布:淘宝定时开售怎么设置 编辑:程序博客网 时间:2024/06/06 17:43

这几天一直静不下心,做题一点都没有效率。也可能是动态规划这边的题目实在是有点难度,所以有时候搞一道题目都弄的很长时间,很悲催。在一个就是自己的智商不怎么样。

这道题目的意思是给你一个序列,求出以这个序列为准的,所有的树。

这样就得实用递归求解了,也就是每个树都可以分成左子树和右子树,这两种书其实又可以看成是独立的树。所以就分成了子问题求解,非常的不错。

递推方程就是 dp(i, j) = sum(dp(i + 1, k - 1) * dp(k, j))。当然k是从1 - len - 1的。这样就可以把所有的树都可以求出来了。就是我用的是vis记忆化搜索,也可以使d[i] = -1,记忆化搜索。

贴出代码:

#include <stdio.h>#include <string.h>#include <iostream>#include <string>using namespace std;const int MOD = 1000000000;char str[333];int d[333][333];int vis[333][333];int dp(int i, int j){if (vis[i][j]){return d[i][j];}vis[i][j] = 1;if (i == j){d[i][j] = 1;return 1;}if (str[i] != str[j]){d[i][j] = 0;return 0;}int& ans = d[i][j];for (int k = i + 2; k <= j; k++){if (str[i] == str[k]){ans = (ans + (long long)dp(i + 1, k - 1) * (long long)dp(k, j)) % MOD;}}return ans;}int main(){while (scanf("%s", str) != EOF){int len = strlen(str);memset(vis, 0, sizeof(vis));memset(d, 0, sizeof(d));printf("%d\n", dp(0, len - 1));}//system("pause");return 0;}

 

原创粉丝点击