0-1背包问题的递归非递归两种解决方法

何为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);
}


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值