java多重背包算法,HDU--2844-Coins(多重背包二进制优化)

该博客讨论了一个关于计算可以使用特定面额硬币组合支付的价格数量的问题。这是一个优化版的多重背包问题,博主首先尝试了使用母函数解决但超时,然后转向采用二进制优化的完全背包算法。通过遍历所有商品及其数量,博主实现了计算从1到m所有可能总价的方法,并给出了C++代码实现。
摘要由CSDN通过智能技术生成

Problem Description

Whuacmers

use coins.They have coins of value A1,A2,A3...An Silverland dollar. One

day Hibix opened purse and found there were some coins. He decided to

buy a very nice watch in a nearby shop. He wanted to pay the exact

price(without change) and he known the price would not more than m.But

he didn't know the exact price of the watch.

You are to write a

program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to

the number of Tony's coins of value A1,A2,A3...An then calculate how

many prices(form 1 to m) Tony can pay use these coins.

Input

The

input contains several test cases. The first line of each test case

contains two integers n(1 ≤ n ≤ 100),m(m ≤ 100000).The second line

contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1 ≤ Ai ≤

100000,1 ≤ Ci ≤ 1000). The last test case is followed by two zeros.

Output

For each test case output the answer on a single line.

Sample Input3 10

1 2 4 2 1 1

2 5

1 4 2 1

0 0

Sample Output8

4

题意:

给你两个整数 n,m 分别表示物品的个数和总额。

然后一行2*n个数,前n个是物品的单价,后n个对应物品的数量。求能凑到 1~m的个数。

题解:

一开始用母函数写了下,果断超时,美滋滋。

然后一看是优化版的多重背包。

我使用的是二进制优化的背包,

二进制背包优化就是利用:

1~ m可以用这些数的组合构成: 1 2 4 8..2^x (+ 剩余的数)。

ps:估摸相同原理,母函数二进制优化应该也可以做,理论AC 理论AC哈。#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define inf 0x3f3f3f3f

#define ll long long

#define sscc ios::sync_with_stdio(false);

#define ms(a) memset(a,0,sizeof(a))

#define mss(a) memset(a,-1,sizeof(a))

#define msi(a) memset(a,inf,sizeof(a))

using namespace std;

int a[205][2];

int dp[200005];

int vis[200005];

int main(){

sscc;

int n,m;

while(cin>>n>>m&&(n+m))

{

ms(dp),ms(vis);

for(int i=1;i<=n;i++){//价格

cin>>a[i][0];

}

for(int i=1;i<=n;i++){//重量

cin>>a[i][1];

}

for(int i=1;i<=n;i++){

if(a[i][0]*a[i][1]<=m){//二进制优化的完全背包

for(int j=1;j<=a[i][1];j<<=1){//二进制

for(int k=m;k>=j*a[i][0];k--){

dp[k]=max(dp[k],dp[k-j*a[i][0]]+j*a[i][0]);

vis[dp[k]]=1;

}

a[i][1]-=j;

}

for(int k=m;k>=a[i][1]*a[i][0];k--){//二进制后剩余值的计算

dp[k]=max(dp[k],dp[k-a[i][1]*a[i][0]]+a[i][1]*a[i][0]);

vis[dp[k]]=1;

}

}

else{//看成是完全背包

for(int k=a[i][0];k<=m;k++){

dp[k]=max(dp[k],dp[k-a[i][0]]+a[i][0]);

vis[dp[k]]=1;

}

}

}

cout<

}

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值