您的位置:首页 > 其它

【多重背包+完全背包】HDU3591The trouble of Xiaoqian

2016-04-07 20:17 274 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3591

Problem Description

In the country of ALPC , Xiaoqian is a very famous mathematician. She is immersed in calculate, and she want to use the minimum number of coins in every shopping. (The numbers of the shopping include the coins she gave the store and the store backed to her.)

And now , Xiaoqian wants to buy T (1 ≤ T ≤ 10,000) cents of supplies. The currency system has N (1 ≤ N ≤ 100) different coins, with values V1, V2, ..., VN (1 ≤ Vi ≤ 120). Xiaoqian is carrying C1 coins of value V1, C2 coins of value V2, ...., and CN coins of
value VN (0 ≤ Ci ≤ 10,000). The shopkeeper has an unlimited supply of all the coins, and always makes change in the most efficient manner .But Xiaoqian is a low-pitched girl , she wouldn’t like giving out more than 20000 once.

 

Input

There are several test cases in the input.

Line 1: Two space-separated integers: N and T. 

Line 2: N space-separated integers, respectively V1, V2, ..., VN coins (V1, ...VN) 

Line 3: N space-separated integers, respectively C1, C2, ..., CN

The end of the input is a double 0.

 

Output

Output one line for each test case like this ”Case X: Y” : X presents the Xth test case and Y presents the minimum number of coins . If it is impossible to pay and receive exact change, output -1.

 

Sample Input

3 70
5 25 50
5 2 1
0 0

 

Sample Output

Case 1: 3

题意:货币系统有 N 种不同面值的钱,每种钱的价值分别为 V1,V2,...,VN 一个人要买价值和为 T 的商品,他每种分别相应的带了 C1,C2,...,CN ,然后问你交易完成后所需要经手的钱币最少数目

代码:

/*
思路整理:
因为m最大为10000,ci最大也为10000,所以f[20000]就够了;
首先,我们可以用多重背包,计算最小的f[j],即支付j元需要支付的最小个数;
然后我们需要的就是计算找零j-m的最小个数;
因为服务员找零每种数量不限,即为完全背包;
所以我们可以枚举f[j]+f[j-m]的最小值;其中j>m;
*/
#include<iostream>
#include<cstring>
#include<algorithm>
#define inf 1<<29
using namespace std;
int f[20050],f2[20050];     //  这个数组开小了,越界会导致c数组数据出错;
int c[150],w[150];      //  c[0,10000],w[1,120]
int n,m;                //  n[1,100],m[1,10000]
void ZeroOnePack(int c,int v,int k)
{
for(int i=20000;i>=c;i--)
f[i]=min(f[i],f[i-c]+v);
}
void CompletePack(int c,int v)
{
for(int i=c;i<=20000;i++)
f[i]=min(f[i],f[i-c]+v);
}
void MultiplePack(int c,int v,int cnt)
{
if(cnt*c>=m){
CompletePack(c,v);
return ;
}else{
int k=1;
while(k<=cnt){
ZeroOnePack(c*k,v*k,k);
cnt-=k;
k<<1;
}
ZeroOnePack(cnt*c,cnt*v,cnt);
}
}
void CompletePack2()
{
for(int i=0;i<n;i++){
for(int j=c[i];j<=20000;j++){
f2[j]=min(f2[j],f2[j-c[i]]+1);
}
}
}
int main()
{
int Case=1;
while(cin>>n>>m&&n+m){
for(int i=0;i<n;i++)
cin>>c[i];
for(int i=0;i<n;i++)
cin>>w[i];

for(int i=1;i<=20000;i++){
f[i]=inf;
f2[i]=inf;
}
f[0]=0;f2[0]=0;
for(int i=0;i<n;i++)
MultiplePack(c[i],1,w[i]);
CompletePack2();
int ans=inf;
for(int i=m;i<=20000;i++){
ans=min(ans,f[i]+f2[i-m]);
}
if(ans==inf) ans=-1;
cout<<"Case "<<Case++<<": "<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: