POJ 3260 The Fewest Coins 最少硬币个数(完全背包+多重背包,混合型)

题意:FJ身上有各种硬币,但是要买m元的东西,想用最少的硬币个数去买,且找回的硬币数量也是最少(老板会按照最少的量自动找钱),即掏出的硬币和收到的硬币个数最少。

思路:老板会自动找钱,且按最少的找,硬币数量也不限,那么可以用完全背包得出组成每个数目的硬币最少数量。而FJ带的钱是有限的,那么必须用多重背包,因为掏出的钱必须大于m,那么我们所要的是大于等于m钱的硬币个数,但是FJ带的钱可能很多,超过m的很多倍都可能,那么肯定要有个背包容量上限,网上说的根据抽屉原理是m+max*max,这里的max指的是最大面值。而给多了的钱上限是max*max,那么找回的钱也必须是max*max,所以完全背包部分的背包容量是max*max。穷举这max*max个可能就行了。

我的思路:与上面不同的是多重背包的容量应该是m+max,因为如果需要找回的钱大于max,那么老板也只是拿多几张最大面额的给你而已。比如买条烟1329块钱,13+1+1+4=19张RMB, 那么我们可以给他14张,15张,16张,17张,18张100的,老板会相应找回71块,171块,271块,371块,471块,你再往上加钱的话,老板也只是拿更多的100还你,这是多余的。那么最多不会超过一张一百(最大面额)的,也就是1329+100=1429为背包容量。错了很多次!

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define INF 0x0ffffffa
 6 using namespace std;
 7 const int N=120;
 8 const int limit=30000;
 9 int n, t;
10 int com[limit];    //完全背包
11 int mul[limit];    //多重背包
12 int big;
13 struct node
14 {
15     int v,c;
16 }coin[N];
17
18 int cal()
19 {
20     for(int i=1; i<=big*big; i++)        com[i]=INF;
21     com[0]=0;
22     for(int i=0; i<n; i++)        //完全背包
23     {
24         for(int j=0; j+coin[i].v<=big*big; j++) //上限big*big
25         {
26             if(com[j+coin[i].v]>com[j]+1)
27                 com[j+coin[i].v]= com[j]+1 ;
28         }
29
30     }
31
32     int upto= t+ big*big;   //多重背包上限
33     for(int i=1; i<=upto; i++)        mul[i]=INF;
34     mul[0]=0;
35     for(int i=0; i<n; i++ )        //多重背包:01背包+二进制
36     {
37         int k=1,tmp=coin[i].c;
38         while(1)
39         {
40             if(k>tmp&&tmp)    k=tmp;
41             else if(k>tmp)        break;
42             for(int j=upto; j>=k*coin[i].v; j-- )
43                 if(mul[j-k*coin[i].v ]!=INF&&mul[j-k*coin[i].v]+k<mul[j])
44                     mul[j]=mul[j-k*coin[i].v]+k;
45             tmp-=k;
46             k<<=1;
47         }
48     }
49     int ans=mul[t]; //刚好给t元
50     for(int i=t+1,j=1; i<upto; i++,j++ )
51     {
52         if(com[j]==INF || mul[i]==INF)    continue;   //INF的表示不能刚好凑成这个价,滤掉。
53         else if(ans>mul[i]+com[j] )    ans= mul[i]+com[j];
54     }
55
56     if(ans==INF)    return -1;
57     return ans;
58 }
59 int main()
60 {
61     //freopen("input.txt","r",stdin);
62     while(cin>>n>>t)
63     {
64         big=-1;
65         for(int i=0; i<n; i++)
66         {
67             scanf("%d",&coin[i].v);
68             if(big<coin[i].v)    big=coin[i].v;
69         }
70         for(int i=0; i<n; i++)    scanf("%d",&coin[i].c);
71         printf("%d\n",cal());
72     }
73
74     return 0;
75 }

AC代码

时间: 2024-08-28 22:02:19

POJ 3260 The Fewest Coins 最少硬币个数(完全背包+多重背包,混合型)的相关文章

POJ 3260 The Fewest Coins(多重背包+全然背包)

http://poj.org/problem?id=3260 题意: John要去买价值为m的商品. 如今的货币系统有n种货币,相应面值为val[1],val[2]-val[n]. 然后他身上每种货币有num[i]个. John必须付给售货员>=m的金钱, 然后售货员会用最少的货币数量找钱给John. 问你John的交易过程中, 他给售货员的货币数目+售货员找钱给他的货币数目 的和最小值是多少? 分析: 本题与POJ 1252类型: http://blog.csdn.net/u013480600

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块钱这种货币单位 考虑一种极限的情况

洛谷P2851 [USACO06DEC]最少的硬币The Fewest Coins(完全背包+多重背包)

题目描述 Farmer John has gone to town to buy some farm supplies. Being a very efficient man, he always pays for his goods in such a way that the smallest number of coins changes hands, i.e., the number of coins he uses to pay plus the number of coins he

POJ 3260 完全背包+多重背包+思维

传送门:https://vjudge.net/problem/20465/origin 题意:你有n种钞票,面值为c[i],数量为v[i],便利店老板有无数张面值为c[i]的钞票,问你买一个价值为T的物品,最少需要经手多少张钞票,老板找零的钞票数也算经手的钞票数 题解:因为我的钞票是有限的,所以将自己看作一个多重背包,老板的钞票是无限的,所以将老板的钞票看做一个完全背包,定义状态dp[i]最少花费多少张钞票可以买价值为i的物品 边界:dp[0]=0; 目的:ans=min(dp1[i]+dp2[

[USACO06DEC]最少的硬币The Fewest Coins

题目描述 约翰在镇上买了 T 元钱的东西,正在研究如何付钱.假设有 N 种钞票,第 i 种钞票的面值为 Vi,约翰身上带着这样的钞票 Ci 张.商店老板罗伯是个土豪,所有种类的钞票都有无限张.他们有洁癖,所以希望在交易的时候,交换的钞票张数尽可能地少.请告诉约翰如何恰好付掉 T 元,而且在过程中交换的货币数量最少. 输入格式 ? 第一行:两个整数 N 和 T,1 ≤ N ≤ 100, 1 ≤ T ≤ 10000 ? 第二行:n个整数 Vi 第三行:n个整数 Ci,1 ≤ Vi ≤ 120, 0

POJ 1276 Cash Machine(多重背包的二进制优化)

题目网址:http://poj.org/problem?id=1276 思路: 很明显是多重背包,把总金额看作是背包的容量. 刚开始是想把单个金额当做一个物品,用三层循环来 转换成01背包来做.T了-- 后面学习了 用二进制来处理数据. 简单地介绍一下二进制优化:?(? ? ??)  假设数量是8,则可以把它看成是1,2,4,1的组合,即这4个数的组合包括了1-8的所有取值情况.这是为什么呢?将它们转换成二进制再观察一下: 1:1 2:10 4:100 1:1 二进制都只有0,1.所以1,2,4

HDU 2844 Coins【多重背包】

大意: 有n种物品 告诉你每种物品的价值和数量 问你能拼凑出1--m之内的多少个数 分析: 多重背包 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int maxn = 100005; 7 int dp[maxn]; 8 int num[maxn], va[maxn]; 9 int vo[maxn]; 10 int n

混合背包(多重背包+完全背包)—— POJ 3260

对应POJ题目:点击打开链接 The Fewest Coins Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5450   Accepted: 1653 Description Farmer John has gone to town to buy some farm supplies. Being a very efficient man, he always pays for his goods in such a

POJ3260——The Fewest Coins(多重背包+完全背包)

The Fewest Coins DescriptionFarmer John has gone to town to buy some farm supplies. Being a very efficient man, he always pays for his goods in such a way that the smallest number of coins changes hands, i.e., the number of coins he uses to pay plus