这是个多重背包问题。。
可以把这个转化成01背包和完全背包的合体来做。做法是枚举每一件物品,如果发现在这件物品的数量乘以价格超过了cash,就可以把这个物品的数量当成无限来做,也就是完全背包。
否则的话,就把这nk[i]件物品拆分成为多件物品,每件物品相对于原先的数量1 , 2 , 4 ,6 ,。。。。。。,2*k件,其中2*k <= nk[i]/2。1-nk[i]的数,都可以由这些数组合而成。于是01背包。
也可以转化成完全背包来做,只需要用一个mem[j]数组记录在总价值为j时,当前物品的使用数量。如果等于或超过了nk[i],就不取了。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int dp[100011],mem[100011];
int main()
{
int cash,n,nk[12],dk[12],i,j,k;
while (scanf("%d",&cash) != EOF)
{
scanf("%d",&n);
for (i=1; i<=n; i++)
{
scanf("%d%d",nk+i,dk+i);
}
memset(dp,0,sizeof(dp));
for (i=1;i<=n; i++)
{
memset(mem,0,sizeof(mem));
for (j=1; j<=cash; j++)
{
if (j-dk[i] < 0)
continue;
if (mem[j-dk[i]] < nk[i] && dp[j] < dp[j-dk[i]]+dk[i])
{
dp[j]=dp[j-dk[i]]+dk[i];
mem[j]=mem[j-dk[i]]+1;
}
}
}
printf("%d\n",dp[cash]);
}
}