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;
}