首页 > 代码库 > AOJ 169 找零钱 DP OR 母函数
AOJ 169 找零钱 DP OR 母函数
一直觉得这题因为有总量限制,是不能用母函数解的,今天偶然发现原来是可以的,记录一下。
只要搞母函数的时候多开一维来表示用了多少个硬币就好了,其实就是目标状态是二维的母函数
类似于 假设我现在要处理的面值是2 (1 + x^2 * y + x^4 * y ^ 2 + x ^ 6 * y ^ 3...) 就表示用0个,1个,2个,3个..硬币的状态了。
看来母函数最重要的还是对式子本身的理解,这样才能应对各种变化。
#include <cstdio>#include <cstring>#include <iostream>#include <map>#include <set>#include <vector>#include <string>#include <queue>#include <deque>#include <bitset>#include <list>#include <cstdlib>#include <climits>#include <cmath>#include <ctime>#include <algorithm>#include <stack>#include <sstream>#include <numeric>#include <fstream>#include <functional>using namespace std;#define MP make_pair#define PB push_backtypedef long long LL;typedef unsigned long long ULL;typedef vector<int> VI;typedef pair<int,int> pii;const int INF = INT_MAX / 3;const double eps = 1e-8;const LL LINF = 1e17;const double DINF = 1e60;const int maxk = 7;const int maxc = 105;const int maxn = 255;const int Coins[] = {1, 2, 5, 10, 20, 50, 100};int C1[maxn][maxc], C2[maxn][maxc];int f[maxn];void init() { C1[0][0] = 1; //用哪种硬币 for(int i = 0; i < maxk; i++) { //用几个 for(int j = 0; j * Coins[i] <= 250; j++) { //枚举从哪里更新 for(int k = 0; k + j * Coins[i] <= 250; k++) { //附加一层循环控制总量 for(int l = 0; l + j <= 100; l++) { C2[k + j * Coins[i]][l + j] += C1[k][l]; } } } memcpy(C1,C2,sizeof C1); memset(C2,0,sizeof C2); } //累加每种硬币总数的情况 for(int i = 0;i <= 250;i++) { for(int j = 0;j <= 100;j++) f[i] += C1[i][j]; }}int main() { init(); int n; while(scanf("%d", &n), n) printf("%d\n",f[n]); return 0;}
当然因为这里没有硬币的上下数量限制,用DP搞很轻松随意
#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <climits>#include <string>#include <iostream>#include <map>#include <cstdlib>#include <list>#include <set>#include <queue>#include <stack> using namespace std; typedef long long LL; int N,C[7] = {1,2,5,10,20,50,100};int f[100][7][250];int dfs(int now,int prev,int sum) { if(sum == 0) return 1; if(sum < 0) return 0; if(now == 100) return 0; int ret = 0,¬e = f[now][prev][sum]; if(note != -1) return note; for(int i = prev;i < 7;i++) { ret += dfs(now + 1,i,sum - C[i]); } return note = ret;} int main() { memset(f,-1,sizeof(f)); while(cin >> N,N) { cout << dfs(0,0,N) << endl; } return 0;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。