题意:有1,5,10,25,50五种硬币,给出一个数字,问又几种凑钱的方式能凑出这个数。
经典的dp题。。。可以递推也可以记忆化搜索。。。
我个人比较喜欢记忆化搜索,递推不是很熟练。
记忆化搜索:很白痴的算法,直接交给下一层去算,算完记录下来以免之后重复算。
代码:
/* * Author: illuz <iilluzen[at]gmail.com> * Blog: http://blog.csdn.net/hcbbt * File: _uva674.cpp * Create Date: 2013-09-20 14:00:42 * Descripton: dp, memorial */ #include <cstdio> #include <cstring> const int MAXN = 8000; const int coin[5] = {1, 5, 10, 25, 50}; int n; long long dp[MAXN][5]; long long solve(int i, int s) { if (dp[s][i] != -1) return dp[s][i]; dp[s][i] = 0; for (int j = i; j < 5 && s >= coin[j]; j++) dp[s][i] += solve(j, s - coin[j]); return dp[s][i]; } int main() { memset(dp, -1, sizeof(dp)); for (int i = 0; i < 5; i++) dp[0][i] = 1; while (scanf("%d", &n) != EOF) printf("%lld\n", solve(0, n)); return 0; }
递推:自底向上的方法,需要注意的是1+5和5+1是一种的,所以要处理一下,从小往大排就不会错了。
代码:
/* * Author: illuz <iilluzen[at]gmail.com> * Blog: http://blog.csdn.net/hcbbt * File: uva674.cpp * Create Date: 2013-09-20 13:48:56 * Descripton: dp, low to up */ #include <cstdio> const int MAXN = 8000; int n, coin[5] = {1, 5, 10, 25, 50}; long long dp[MAXN] = {1}; int main() { for (int i = 0; i < 5; i++) for (int j = 0; j < MAXN - 100; j++) dp[j + coin[i]] += dp[j]; while (scanf("%d", &n) != EOF) printf("%lld\n", dp[n]); return 0; }