ACM学习历程——HDU1331 Function Run Fun(锻炼多维dp的打表)
2014-11-20 20:32
274 查看
Description
We all love recursion! Don't we?
Consider a three-parameter recursive function w(a, b, c):
if a <= 0 or b <= 0 or c <= 0, then w(a, b, c) returns: 1
if a > 20 or b > 20 or c > 20, then w(a, b, c) returns: w(20, 20, 20)
if a < b and b < c, then w(a, b, c) returns: w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c)
otherwise it returns: w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1)
This is an easy function to implement. The problem is, if implemented directly, for moderate values of a, b and c (for example, a = 15, b = 15, c = 15), the program takes hours to run because of the massive recursion.
Input
The input for your program will be a series of integer triples, one per line, until the end-of-file flag of -1 -1 -1. Using the above technique, you are to calculate w(a, b, c) efficiently and print the result.
Output
Print the value for w(a,b,c) for each triple.
Sample Input
1 1 1
2 2 2
10 4 6
50 50 50
-1 7 18
-1 -1 -1
Sample Output
w(1, 1, 1) = 2
w(2, 2, 2) = 4
w(10, 4, 6) = 523
w(50, 50, 50) = 1048576
w(-1, 7, 18) = 1
递推的式子是直接给出来的。里面最关键的两个式子是:
f[i][j][k] = f[i][j][k-1] + f[i][j-1][k-1] - f[i][j-1][k];
以及
f[i][j][k] = f[i-1][j][k] + f[i-1][j-1][k] + f[i-1][j][k-1] - f[i-1][j-1][k-1];
可知这个三维dp式子,前一个式子都是在i那一维,通过特征观察可知,是j一层一层递推的(或者k)。
而第二个式子又可以看出是i一层层的递推。
故递推的时候只需要三个for循环就搞定。
但是还需要注意的是
任意i,j,f[i][j][0] = f[i][0][j] = f[0][i][j] = 1;
这个条件给每一维的0这个面都赋成了1,有了这个初始化,就可以放心地递推了。
代码:
We all love recursion! Don't we?
Consider a three-parameter recursive function w(a, b, c):
if a <= 0 or b <= 0 or c <= 0, then w(a, b, c) returns: 1
if a > 20 or b > 20 or c > 20, then w(a, b, c) returns: w(20, 20, 20)
if a < b and b < c, then w(a, b, c) returns: w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c)
otherwise it returns: w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1)
This is an easy function to implement. The problem is, if implemented directly, for moderate values of a, b and c (for example, a = 15, b = 15, c = 15), the program takes hours to run because of the massive recursion.
Input
The input for your program will be a series of integer triples, one per line, until the end-of-file flag of -1 -1 -1. Using the above technique, you are to calculate w(a, b, c) efficiently and print the result.
Output
Print the value for w(a,b,c) for each triple.
Sample Input
1 1 1
2 2 2
10 4 6
50 50 50
-1 7 18
-1 -1 -1
Sample Output
w(1, 1, 1) = 2
w(2, 2, 2) = 4
w(10, 4, 6) = 523
w(50, 50, 50) = 1048576
w(-1, 7, 18) = 1
递推的式子是直接给出来的。里面最关键的两个式子是:
f[i][j][k] = f[i][j][k-1] + f[i][j-1][k-1] - f[i][j-1][k];
以及
f[i][j][k] = f[i-1][j][k] + f[i-1][j-1][k] + f[i-1][j][k-1] - f[i-1][j-1][k-1];
可知这个三维dp式子,前一个式子都是在i那一维,通过特征观察可知,是j一层一层递推的(或者k)。
而第二个式子又可以看出是i一层层的递推。
故递推的时候只需要三个for循环就搞定。
但是还需要注意的是
任意i,j,f[i][j][0] = f[i][0][j] = f[0][i][j] = 1;
这个条件给每一维的0这个面都赋成了1,有了这个初始化,就可以放心地递推了。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <set> #include <map> #include <vector> #include <queue> #include <string> #define inf 0x3fffffff #define eps 1e-10 using namespace std; int f[25][25][25]; void Init() { for (int i = 0; i <= 20; i++) for (int j = 0; j <= 20; j++) f[i][j][0] = f[i][0][j] = f[0][i][j] = 1; for (int i = 1; i <= 20; i++) for (int j = 1; j <= 20; j++) for (int k = 1; k <= 20; k++) { if (i < j && j < k) f[i][j][k] = f[i][j][k-1] + f[i][j-1][k-1] - f[i][j-1][k]; else f[i][j][k] = f[i-1][j][k] + f[i-1][j-1][k] + f[i-1][j][k-1] - f[i-1][j-1][k-1]; } } int w(int a, int b, int c) { if (a <= 0 || b <= 0 || c <= 0) return 1; if (a > 20 || b > 20 || c > 20) return f[20][20][20]; return f[a][b][c]; } int main() { //freopen("test.txt", "r", stdin); Init(); int a, b, c; while (scanf("%d%d%d", &a, &b, &c) != EOF) { if (a == -1 && b == -1 && c == -1) break; printf("w(%d, %d, %d) = ", a, b, c); printf("%d\n", w(a, b, c)); } return 0; }
相关文章推荐
- ACM-DP之Function Run Fun——hdu1331
- ACM学习历程—HDU1003 Max Sum(dp && 最大子序列和)
- ACM学习历程—HDU5587 Array(数学 && 二分 && 记忆化 || 数位DP)(BestCoder Round #64 (div.2) 1003)
- ACM学习历程—CodeForces 176B Word Cut(字符串匹配 && dp && 递推)
- ACM学习历程—HDU1584 蜘蛛牌(动态规划 && 状态压缩 || 区间DP)
- ACM学习历程—ZOJ3471 Most Powerful(dp && 状态压缩 && 记忆化搜索 && 位运算)
- ACM学习历程—FZU2195 检查站点(树形DP || 贪心)
- ACM学习历程—POJ1088 滑雪(dp && 记忆化搜索)
- ACM学习历程——HDU2227 Find the nondecreasing subsequences(线段树 && dp)
- ACM学习历程—HDU 1059 Dividing(dp && 多重背包)
- Function Run Fun (HDU 1331) —— 记忆化搜索DP
- ACM学习历程——HDU5017 Ellipsoid(模拟退火)(2014西安网赛K题)
- ACM学习历程——HDU4472 Count(数学递推) (12年长春区域赛)
- ACM学习历程—HDU1028 Ignatius and the Princess(组合数学)
- ACM学习历程——HDU 5014 Number Sequence (贪心)(2014西安网赛)
- ACM学习历程—FZU2148 Moon Game(计算几何)
- ACM学习历程——POJ3295 Tautology(搜索,二叉树)
- ACM学习历程——ZOJ 3829 Known Notation (2014牡丹江区域赛K题)(策略,栈)
- ACM学习历程——UVA 127 "Accordian" Patience(栈;模拟)
- ACM学习历程—HDU4956 Poor Hanamichi(模拟)