一种优化方法思路来自于hdu2844 Coins
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
bool dp[100010];
int used[100010];
int cash,n,nn,dd;
int main(){
while(scanf("%d",&cash)!=EOF){
scanf("%d",&n);
memset(dp,false,sizeof(dp));
dp[0]=true;
int i,j,k;
for(i=1;i<=n;i++){
memset(used,0,sizeof(used));
scanf("%d%d",&nn,&dd);
if(nn*dd>cash){
for(j=dd;j<=cash;j++)
if(dp[j-dd]) dp[j]=true;
}else{
for(k=dd;k<=cash;k++)
if(!dp[k]&&dp[k-dd]&&used[k-dd]<nn){
dp[k]=true;
used[k]=used[k-dd]+1;
}
}
}
int ii;
for(ii=cash;ii>=0;ii--){
if(dp[ii]){
printf("%d\n",ii);
break;
}
}
if(ii==-1){
printf("0\n");
continue;
}
}
return 0;
}
另一种是背包九讲里的二进制优化方法
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
bool dp[100010];
int cash,n,nn,dd;
int main(){
while(scanf("%d",&cash)!=EOF){
scanf("%d",&n);
memset(dp,false,sizeof(dp));
dp[0]=true;
int i,k,l;
for(i=1;i<=n;i++){
scanf("%d%d",&nn,&dd);
if(nn*dd>cash){
for(l=dd;l<=cash;l++)
if(dp[l-dd]) dp[l]=true;
}else{
int bit=1;
while(bit<nn){
int money=bit*dd;
for(k=cash;k>=money;k--)
if(dp[k-money]) dp[k]=true;
nn-=bit;
bit<<=1;
}
for(k=cash;k>=nn*dd;k--)
if(dp[k-nn*dd]) dp[k]=true;
}
}
int ii;
for(ii=cash;ii>=0;ii--){
if(dp[ii]){
printf("%d\n",ii);
break;
}
}
if(ii==-1){
printf("0\n");
continue;
}
}
return 0;
}