题目链接地址:http://acm.hdu.edu.cn/showproblem.php?pid=1114
这是一道完全背包问题,可以讲完全背包问题转换为01背包问题解,也可以直接求解。完全背包问题的状态转移方程为:f[i][v]=max{f[i-1][v],f[i][v-c[i]]+w[i]}。需要注意的是本题不是求最大值而是求最小值,所以初始化的时候要注意。
1、转化为01背包问题的代码:
#include<stdio.h>
#include<limits.h>
int main(){
//freopen("1.txt","r",stdin);
int T,E,F,N;
int W[501],V[501];
int nWeight[8000],nValue[8000],dp[10010]; //
scanf("%d",&T);
while(T--){
scanf("%d%d",&E,&F);
scanf("%d",&N);
int index=0;
for(int i=0;i<N;i++){
scanf("%d%d",&V[i],&W[i]);
int k=1;
while(k*W[i]<=(F-E)){
nWeight[index]=k*W[i];
nValue[index++]=k*V[i];
k*=2;
}
}
dp[0]=0;
for(int i=1;i<=F-E;i++)
dp[i]=1000000001;
for(int i=0;i<index;i++){
for(int j=(F-E);j>=nWeight[i];j--){
if(dp[j]>(dp[j-nWeight[i]]+nValue[i])){
dp[j]=dp[j-nWeight[i]]+nValue[i];
}
}
}
if(dp[F-E]==1000000001)
printf("This is impossible.\n");
else
printf("The minimum amount of money in the piggy-bank is %d.\n",dp[F-E]);
}
return 0;
}
2、直接利用完全背包问题的状态转移方程的解法:
#include<stdio.h>
const int INF=1000000001;
int main(){
//freopen("1.txt","r",stdin);
int T,E,F,N;
int V[501],W[501],dp[10001];
scanf("%d",&T);
while(T--){
scanf("%d%d",&E,&F);
scanf("%d",&N);
for(int i=0;i<N;i++)
scanf("%d%d",&V[i],&W[i]);
F=F-E;
for(int i=1;i<=F;i++)
dp[i]=INF;
dp[0]=0;
for(int i=0;i<N;i++){
for(int j=W[i];j<=F;j++){
if(dp[j]>dp[j-W[i]]+V[i])
dp[j]=dp[j-W[i]]+V[i];
}
}
if(dp[F]==INF)
printf("This is impossible.\n");
else
printf("The minimum amount of money in the piggy-bank is %d.\n",dp[F]);
}
return 0;
}
关于3种背包问题的详细解法请参考:TankyWoo大神的帖子。