poj 3260 The Fewest Coins 多重背包+完全背包
题目链接:http://poj.org/problem?id=3260
给店家的钱是多重背包 dp[]
店家的找钱是完全背包 dp2[]
然后最后 其中i表示多给了多少钱 也就是需要找回多少钱
int ans = INF;
ans = min(ans, dp[m+i] + dp2[i]);
是一个比较简单的思路
神坑题
看到每种货币的面值不大于120 我就觉得找钱一定不会超过119块钱结果wa到死
后来才发现不是的啊
之所以我有这种思维定式是因为现实生活中有1块钱这种货币单位
考虑一种极限的情况
只有面值为120元、119元两种货币
然后你只有120那种 要去买价值为120*82 + 119 = 9959元的东西
那119的部分需要你给店家119张120块钱让他找你119张119块钱Orz 【三观啊...
这样一来可以大概估计找钱的一个上界是14400
所以两个DP过程的容量都加上14400然后再去做就能过T^T
另外写CompletePack2()的时候我明明没有改V的值可是V的值变了
后来才反应过来这种事情很可能就是数组越界
检查了一下果然边界情况没有控制好
#include <cstdio> #include <cstdlib> #include <ctime> #include <iostream> #include <cmath> #include <cstring> #include <algorithm> #include <stack> #include <set> #include <queue> #include <vector> using namespace std; typedef long long ll; const int maxn = 110; const int maxm = 10200; const int INF = 100000; int a[maxn], c[maxn]; int dp[maxm + 15000]; int dp2[15000]; int V; void ZeroOnePack(int cost, int weight) { for(int i = V; i >= cost; i--) { dp[i] = min(dp[i], dp[i-cost] + weight); } } void CompletePack(int cost, int weight) { for(int i = cost; i <= V; i++) { dp[i] = min(dp[i], dp[i-cost] + weight); } } void MultiplePack(int cost, int weight, int amount) { if(cost*amount >= V) { CompletePack(cost, weight); return; } int k = 1; while(k < amount) { ZeroOnePack(k*cost, k*weight); amount = amount - k; k *= 2; } ZeroOnePack(amount*cost, amount*weight); } void CompletePack2(int cost, int weight) { for(int i = cost; i < V; i++) { dp2[i] = min(dp2[i], dp2[i-cost] + weight); } } int main() { //freopen("in.txt", "r", stdin); int n, m; while(scanf("%d%d", &n, &m) == 2) { memset(dp, 0x3f, sizeof(dp)); memset(dp2, 0x3f, sizeof(dp2)); dp[0] = dp2[0] = 0; for(int i = 0; i < n; i++) scanf("%d", &a[i]); for(int i = 0; i < n; i++) scanf("%d", &c[i]); V = m + 14400; for(int i = 0; i < n; i++) MultiplePack(a[i], 1, c[i]); V = 14400; for(int i = 0; i < n; i++) { CompletePack2(a[i], 1); } int ans = INF; for(int i = 0; i < 14400; i++) { ans = min(ans, dp[m+i] + dp2[i]); } if(ans == INF) printf("-1\n"); else printf("%d\n", ans); } return 0; }