0-1背包问题的递归非递归两种解决方法
程序员文章站
2022-04-29 21:46:00
...
何为0-1背包问题?
举个例子,比如我们有物件物品,五件物品分别对应有着自己的重量和价值,此时我们有一个背包,让你去选择随意的装这五件商品,那么我们肯定要选择能最大化利益的一种方法,也就是有限的背包容量,装取最大价值的商品,这也就是0-1背包算法的核心思想。
那么如何去选择这个最优的解?
如图,weight表示物品的重量,value表示物品的价值。
此时的i表示背包的容积,j表示背包所能装下的物体数量。
当i=0时,表示背包所能装的物体为0个,当j等于0时,表示此时背包的容积为0,装不下了。
那么我们便清楚的意识到我们要求的其实就是这张表上最后的这个值。
话不多说,上代码:
//二维数组,非递归
#include <stdio.h>
#include <stdlib.h>
const int N=5;//物品数量
const int S=15;//背包的容量
int tmp1,tmp2;
const int weight[]={1,2,3,4,5};//N件物品的重量
const int value[]={1,3,2,4,5};//价格
int main()
{
int dp[N][S];//背包
int Back[N];//用来存放背包中最大价值物品的编号
int tmp1,tmp2,s=S;
for(int i=0;i<N;i++){ //初始化背包
for(int j=0;j<S;j++){
dp[i][j]=0;
}
}
for(int i=0;i<S;i++){ //找到背包中第一个存放的物品
if(i>=weight[0])
dp[0][i]=1;
}
for(int i=1;i<N;i++){ //找到剩余的所能装下的最大价值的物品
for(int j=1;j<=S;j++){
if(j<weight[i]) //如果背包的剩余容积小于此刻的物品重量,不装
dp[i][j]=dp[i-1][j];
if(j>weight[i]) //背包剩余容积大于物品重量,比较装或者不装所能达到的最大价值,最后选择带来效益最大的解,存入背包中
{
tmp1=dp[i-1][j];
tmp2=value[i]+dp[i-1][j-weight[i]];
dp[i][j]=tmp1>tmp2?tmp1:tmp2;
}
}
}
printf("%d\n",dp[N-1][S]); //求出最优解
for(int i=N-1;i>=0;i--){ //找出所选择物品的编号
if(dp[i][s]>dp[i-1][s]&&i!=0)
{
Back[i]=1;
s-=weight[i];
}
else if(i==0&&s>=weight[i])
Back[i]=1;
else
Back[i]=0;
}
for(int i=0;i<N;i++){
if(Back[i]==1)
printf("%d ",i+1);
}
}
//递归方式:
#include <stdio.h>
#include <stdlib.h>
const int N=5;//物品数量
const int S=15;//背包的容量
const int weight[]= {1,2,3,4,5}; //N件物品的重量
const int value[]= {1,3,2,4,5}; //价格
int backpack(int n,int s)
{
int tmp1=0,tmp2=0,maxx=0;
if(n==0)
return 1;
else if(n<0)
return 0;
else
{
if(s>=weight[n])
{
tmp1=backpack(n-1,s);
tmp2=backpack(n-1,s-weight[n])+value[n];
maxx=tmp1>tmp2?tmp1:tmp2;
}
return maxx;
}
}
int main()
{
int maxn=backpack(N,S);
printf("%d\n",maxn);
}