题意:Tony想要买一个东西,他只有n种硬币,每种硬币的面值为a[i],每种硬币的数量为c[i],要买的物品价值不超过m,输出1-m中有多少种价格Tony可以用硬币组合出来。
题解:多重背包,参考:https://www.cnblogs.com/asuml/p/5730400.html。
#include <iostream> #include <cstring> #define INF 0x3f3f3f3f using namespace std; int f[111111],a[111],c[111]; int n,m; //m背包的总容量、v物品的体积、w物品的价值 void OneZeroPack(int m,int v,int w) //0-1背包 { for(int i=m;i>=v;i--) f[i]=max(f[i],f[i-v]+w); } //m背包的总容量、v物品的体积、w物品的价值 void CompletePack(int m,int v,int w) //完全背包 { for(int i=v;i<=m;i++) f[i]=max(f[i],f[i-v]+w); } //m背包的总容量、v物品的体积、w物品的价值、num物品的数量 void MultiplePack(int m,int v,int w,int num)//多重背包 { if(v*num>=m) { CompletePack(m,v,w); return ; } int k=1; for(k=1;k<=num;k<<=1) { OneZeroPack(m,k*v,k*w); num=num-k; } if(num) OneZeroPack(m,num*v,num*w); } int main() { while(cin>>n>>m) { if(n==0&&m==0) break; for(int i=0;i<n;i++) cin>>a[i]; for(int i=0;i<n;i++) cin>>c[i]; for(int i=0;i<=m;i++) f[i]=-INF; f[0]=0; for(int i=0;i<n;i++) { MultiplePack(m,a[i],a[i],c[i]); } int sum=0; for(int i=1;i<=m;i++) if(f[i]>0) sum++; cout<<sum<<endl; } return 0; }