poj 1787 Charlie's Change(完全背包 或 多重背包 记录路径)
2017-08-14 16:09
561 查看
多重背包,但是可以用完全背包来做。
参考:http://www.cnblogs.com/kuangbin/archive/2012/09/20/2695803.html
多重背包:
参考:http://blog.csdn.net/libin56842/article/details/9470687
学到了记录一种多重背包记录路径的方法。
参考:http://www.cnblogs.com/kuangbin/archive/2012/09/20/2695803.html
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 10010; int dp[MAXN]; int path[MAXN]; int used[MAXN]; int P; int v[4] = {1,5,10,25}; int num[4]; int res[100]; void init() { memset(res,0,sizeof(res)); memset(path,0,sizeof(path)); path[0] = -1; for(int i = 1; i <= P; ++i) dp[i] = -INF; dp[0] = 0; } void solve() { for(int i = 0; i < 4; ++i) { memset(used,0,sizeof(used)); for(int j = v[i]; j <= P; ++j) { //dp[j-v[i]] >= 0如果不设这个条件。used会溢出 //而且dp[j-v[i]]<0的话,也没必要去更新,在这之前的状态组合不出来j-v[i] if(dp[j-v[i]]+1 > dp[j] && dp[j-v[i]] >= 0 && used[j-v[i]] < num[i]) { dp[j] = dp[j-v[i]]+1; used[j] = used[j-v[i]]+1; path[j] = j-v[i]; } } } } int main() { while(scanf("%d",&P)) { scanf("%d %d %d %d",&num[0],&num[1],&num[2],&num[3]); if(P+num[0]+num[1]+num[2]+num[3] == 0) break; init(); solve(); if(dp[P] != -INF) { while(path[P] != -1) { res[P-path[P]]++; P = path[P]; } printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",res[1],res[5],res[10],res[25]); } else printf("Charlie cannot buy coffee.\n"); } return 0; }
多重背包:
参考:http://blog.csdn.net/libin56842/article/details/9470687
学到了记录一种多重背包记录路径的方法。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 10010; int dp[N*10]; int path ; int cent[4] = {1,5,10,25}; int num[4]; int res[30]; int P; void CompletePack(int pos) { for(int j = cent[pos]; j <= P; ++j) { if(dp[j-cent[pos]]+1 > dp[j]) { dp[j] = dp[j-cent[pos]]+1; path[j] = pos*N+j-cent[pos]; } } } void ZeroOnePack(int pos, int k) { for(int j = P; j >= cent[pos]*k; --j) { if(dp[j-k*cent[pos]]+k > dp[j]) { dp[j] = dp[j-k*cent[pos]]+k; path[j] = pos*N+j-k*cent[pos]; } } } void MultiplePack() { for(int i = 0; i < 4; ++i) { if(num[i]*cent[i] >= P) CompletePack(i); else { int temp = num[i]; for(int k = 1; k <= temp; k *= 2) { ZeroOnePack(i,k); temp -= k; } if(temp) ZeroOnePack(i,temp); } } } int main() { int t; while(scanf("%d",&P)) { t = P; for(int i = 0; i < 4; ++i) { scanf("%d",&num[i]); t += num[i]; } if(!t) break; memset(path,0,sizeof(path)); memset(res,0,sizeof(res)); for(int i = 1; i <= P; ++i) dp[i] = -N; dp[0] = 0; MultiplePack(); if(dp[P] < 0) { printf("Charlie cannot buy coffee.\n"); continue; } while(P) { int s1 = path[P]/N;//s1表示货币的种类 int s2 = path[P]%N;//(P-s2)表示这种货币一共多少金额 res[cent[s1]] += (P-s2)/cent[s1]; P = s2; } printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",res[1],res[5],res[10],res[25]); } }
相关文章推荐
- POJ 1787 - Charlie's Change(完全背包+路径记录)
- poj 1787 Charlie's Change【多重背包可行性+记录路径】
- poj1787 Charlie's Change (多重背包+记录路径)
- 【POJ】1787 Charlie's Change(完全背包)
- POJ - 1787 Charlie's Change(完全背包和路径纪录)
- POJ 1787(完全背包+记录路径)
- POJ - 1787 完全背包,记录路径
- 动态规划,多重背包,保存路径,用完全背包的方法做多重背包(Charlie's Change,poj 1787)
- poj 1787 Charlie's Change(多重背包路径记录)
- POJ 1787 Charlie's Change(多重背包+记录路径)
- POJ-1787 Charlie's Change( 多重背包记录方案)
- POJ 1787 Charlie's Change / 完全背包
- POJ 题目1787 Charlie's Change(完全背包)
- poj 1787 Charlie's Change(打印路径的多重背包 ->交易数量最大化)
- POJ-1787 Charlie's Change (完全背包+输出方案 入门题)
- POJ 1784 Charlie's Change 记录路径的多重背包
- poj 1787 多重背包+路径记录
- poj 1787 记录路径的多重背包
- POJ 1787 Change 多重|完全背包
- poj 1787 多重背包记录路径