解题思路:
这其实是一个多重背包的问题,每一次的cash对应于背包的容量,钱的种类即为物品的种类,注意这里钱的面值对应于物品的价值和体积,然后用二进制拆分将多重背包化为0-1背包问题来解决,这里转化后的vv和ww数组也只是同一个数组newarr。注意,最多只有10种钞票,数组a和c的大小设置为15即可,cash最大值为100000,f大小设置为100005,newarr大小应该与新的物品总个数cnt相匹配(相当于每个物品都做一次0-1背包计算)。每一种物品最多有1000个,二进制拆分以后的个数一定小于1000,最多有10种物品,故二进制拆分以后的物品总个数一定小于10000,所以newarr大小设置为10005即可。
参考代码:
#include <iostream>
#include <cstring>
using namespace std;
int v,n;
int a[15];//value(weight)
int c[15];
int f[100005];
int newarr[10005];
int main(int argc, const char * argv[]) {
while (cin>>v>>n) {
for (int i=1; i<=n; i++) {
cin>>c[i]>>a[i];
}
int cnt=0;
for (int i=1; i<=n; i++) {
int t=c[i];
for (int k=1; k<=t; k<<=1) {
cnt++;
newarr[cnt]=k*a[i];
t-=k;
}
if (t>0) {
cnt++;
newarr[cnt]=t*a[i];
}
}
memset(f, 0, sizeof(f));
for (int i=1; i<=cnt; i++)
for(int j=v;j>=0;j--)
{
if(newarr[i]<=j)f[j]=max(f[j], f[j-newarr[i]]+newarr[i]);
}
cout<<f[v]<<endl;
}
return 0;
}