一个裸的多重背包,把物品按二的幂分解,然后就转换成了01背包问题来求解,具体操作可参考《背包问题九讲2.0》。
以下是代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int a[200];
int dp[100010];
int cn=0;
void add(int num,int ww) //将一个物品分解。背包九讲上的模板,挺不错的。
{
int k=1;
while(k<num){
a[++cn]=k*ww;
num-=k;
k*=2;
}
a[++cn]=num*ww;
}
int main()
{
//freopen("in.txt","r",stdin);
int cash;
while(scanf("%d",&cash)!=EOF){
cn=0;
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
int n,nk,w;
scanf("%d",&n);
while(n--){
scanf("%d%d",&nk,&w);
add(nk,w);
} //多重背包问题转换成了01背包问题
for(int i=1;i<=cn;i++)
for(int j=cash;j>=a[i];j--) //从后往前降低空间复杂度。
dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
printf("%d\n",dp[cash]);
}
return 0;
}