HDU 3591 The trouble of Xiaoqian (完全背包+多重背包)

The trouble of Xiaoqian

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2783    Accepted Submission(s): 967


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
 

题意:

你要去商店买东西,但是规定你只能使用规定面额的硬币来支付(每种硬币的数量也是有规定的),售货员所持有规定面额的硬币无限个(用于找零),现在要计算怎样交易最少数量的硬币(包括你给售货员的和售货员找零给你的)来完成交易,注意:单笔交易不得超过20000元。 

分析:对卖家运用完全背包,对买家利用多重背包

代码(不知怎么的TLE了好多次):

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define mod 1000000007
#define mem(a) memset(a,0,sizeof(a))

using namespace std;

const int maxn = 20000 + 5 , inf = 0x3f3f3f3f ;
int dp1[maxn];//买家
int dp2[maxn];//卖家
int v[maxn],c[maxn];
int n,m;

void ZoreOnePack(int dp[],int cost ,int weight){//0 1 背包
    for(int j = maxn-1 ; j >= cost ; j -- )
        dp[j] = min(dp[j],dp[j-cost]+weight);
}

void CompletePack(int dp[],int cost,int weight){//完全背包
    for(int j = cost ; j < maxn ; j ++ )
        dp[j] = min(dp[j],dp[j-cost]+weight);
}

void MultiplePack(int dp[],int cost,int weight,int num){//多重背包
    if(num*cost>=maxn){//当总量大于或等于最大数量时,相反与完全背包
        CompletePack(dp,cost,weight);
        return;
    }
    int k = 1;
    while(k<num){//利用二进制优化为01背包
        ZoreOnePack(dp,k*cost,k*weight);
        num-=k;
        k*=2;
    }
    ZoreOnePack(dp,cost*num,num*weight);//剩下的
}

void init(){//初始化
    for(int i = 1 ; i< maxn ; i ++ ) dp1[i] = dp2[i] = inf;
    dp1[0] = dp2[0] = 0;
}

int main(){
    int iKase = 1;
    while(scanf("%d %d",&n,&m)!=EOF&&n&&m){

        init();

        for(int i = 0 ; i < n ; i ++ ) scanf("%d",&v[i]);
        for(int i = 0 ; i < n ; i ++ ) scanf("%d",&c[i]);

        for(int i = 0 ; i < n ; i ++ ) CompletePack(dp2,v[i],1);
        for(int i = 0 ; i < n ; i ++ ) MultiplePack(dp1,v[i],1,c[i]);

        int ans = inf ;
        //最后结果就是dp1[i]+dp2[i-m]
        for(int i = m ; i < maxn ; i ++ ){
            if(dp1[i]!=inf&&dp2[i-m]!=inf)
            ans = min(ans,dp1[i]+dp2[i-m]);
        }
        if(ans!=inf)
            printf("Case %d: %d\n",iKase++,ans);
        else
            printf("Case %d: -1\n",iKase++);
    }
    return 0 ;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值