01背包问题的多种求解

这篇具有很好参考价值的文章主要介绍了01背包问题的多种求解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.问题描述

问题描述: 有一个容量为V的背包,还有n个物体。现在忽略物体实际几何形状,我们认为只要背包的剩余容量大于等于物体体积,那就可以装进背包里。每个物体都有两个属性,即体积w和价值v。使物品装入背包的价值最大。

2.0-1背包问题的解决思路

    1.方法一:枚举法,首先想到最简单的枚举法,通过列举所有结果,从中筛选出满足题意的结果。

    2.方法二:回溯法,在枚举法的基础上进行约束剪枝和限界剪枝。
    3.方法三:动态规划,运用动态规划思想,动态规划与分治法类似,都是把大问题拆分成小问题,通过寻找大问题与小问题的递推关系,使用递推算法解决一个个小问题,最终达到解决原问题的效果。

2.3.1、如果装不下当前物品,那么前n个物品的最佳组合和前n-1个物品的最佳组合是一样的。
2.3.2、如果装得下当前物品。
假设1 :装当前物品,在给当前物品预留了相应空间的情况下,前n-1个物品的最佳组合加上当前物品的价值就是总价值。
假设2:不装当前物品,那么前n个物品的最佳组合和前n-1个物品的最佳组合是一样
选取假设1和假设2中较大的价值,为当前最佳组合的价值。

3.问题求解中所遇到的问题及分析解决方案;

问题:枚举法和回溯法运算规模较大、时间较长,动态规划中存在重叠子问题,递归方程多次调用自身使时间复杂度较大,01背包问题无法用贪心算法来解决

解决方案:使用动态规划方法时利用备忘录方法解决重复计算的问题,用递推方程替代递归方程

4问题的解决方案

问题求解关键技术:约束剪枝、限界剪枝、备忘录方法

5.算法测试

在比较枚举法,回溯法,动态规划法完成问题的时间复杂度之后,发现动态规划法是该问题的最优解。通过对01背包问题解法的扩展,可解决完全背包、多重背包等一些问题。

枚举法:#include <stdio.h>

#include <stdlib.h>

#include <time.h>

const int N=10;//全局变量,物品数量

const int bag=N;//全局变量,背包承重量

int max_value=0;//全局变量,记录能获得的最大价值

int backpack(int a[],int v[],int w[],int n,int t)

{

   int max_v=0,max_w=0;//背包累积的最大价值和最大重量

   if(t>n-1)//递归结束的条件

   {

       printf("找到一个方案");

       for(int i=0;i<n;i++){//遍历数组a根据其记录的0、1值进行背包价值和重量计算

          printf("%d",a[i]);

          max_v=max_v+v[i]*a[i];//found!!!!!如何计算max_v

          max_w=max_w+w[i]*a[i];//found!!!!!如何计算max_w

       }

       if(max_w>bag)//found!!!!!根据max_w判断该方案是否超重

          printf("\n该方案总价%d,总重%d,超重!不可行!!!\n",max_v,max_w);

       else{//如果不超重

          if(max_v>max_value)//found!!!!!比较该方案所获得的价值是不是比全局最优解更优

              max_value=max_v;//更新最优解

          printf("\n该方案总价%d,总重%d,可行\n",max_v,max_w);

       }

    }else{

        for(int i=1;i>=0;i--)//只取值1或0

        {

            a[t]=i;//记录当前物品选1或不选0

          backpack(a,v,w,n,t+1);//递归到下一层

        }

    }

   return max_value;//返回最大价值

}

int main()

{

   int a[N],v[N],w[N],i,start,end;

   printf("背包最大承重%d公斤\n",bag);

   for(i=0;i<N;i++)//随机生成价值和重量

   {

       v[i]=rand()%5+1;

       w[i]=rand()%5+1;

       printf("物品%d,价值%d,重量%d\n",i,v[i],w[i]);

   }

   start=clock();

   printf("能获得的最大价值为:%d\n",backpack(a,v,w,N,0));

   end=clock();

   printf("耗时:%dms\n",end-start);

   return 0;

}

1-3枚举法运行结果

回溯法:

int backpack(int t,int now_v,int now_w)

{//t表示递归层数,now_v表示当前层所累积的价值,now_w表示当前层所累积的重量

   int i;

   if(t>N-1)//当递归到达叶子节点时

   {

       printf("找到一个方案");

       for(i=0;i<N;i++)

       {

          printf("%d",a[i]);

       }

       if(now_w>bag)//判断方案是否超重

       {

          printf("\n该方案总价%d,总重%d,超重!不可行!!!\n",now_v,now_w);

       }

       else//如果不超重

       {

          if(now_v>max_value)//判断该方案所获得的价值是不是更优

          {

              max_value=now_v;//更新最优解

          }

          printf("\n该方案总价%d,总重%d,可行\n",now_v,now_w);

       }

       count++;

    }

    else

    {

        for(i=0;i<=1;i++)

        {

            a[t]=i;//记录当前物品选或不选

          now_v=now_v+v[t]*i;//根据0-1值累加价值

          now_w=now_w+w[t]*i;//根据0-1值累加重量

          if(now_w<=bag&&now_v+r[t+1]>max_value) // (限件减枝 约束减枝)

              backpack(t+1,now_v,now_w);//递归到下一层

        }

    }

   return max_value;//返回最大价值

}

1-2回溯法运行结果

动态规划:

int jy[100][100]={0};//记忆数组

int backpack(int i,int m)//i为第i个物品,m为有m元钱

{

   if(i == 0) return 0;//边界

   if(jy[i][m]>0)return jy[i][m];

    if(w[i]>m)

       return jy[i][m]=backpack(i-1,m);//当这个物品装不下时 就不需要比较了

    else

       jy[i][m]=max(backpack(i-1,m),backpack(i-1, m - w[i])+v[i]);

   return jy[i][m];

}

1-1动态规划运行结果图

分析算法及运行时间可知枚举法和回溯法的算法复杂度为O(2^n),而动态规划方法的算法复杂度为O(n)

6.总结

枚举法和回溯的思路较简单但是算法复杂度较高,动态规划的方法需要考虑的问题较多但是大大减低了算法复杂度

动态规划算法具有最优子结构性质,因此动态规划能得到最优解。01背包问题存在重叠子问题,利用备忘录方法避免重复计算相同子问题。

注:贪心算法中,每步贪心决策都无法改变,而忽略了背包的容量,考虑的背包问题的局部最优,而不是全局最优。文章来源地址https://www.toymoban.com/news/detail-590976.html

到了这里,关于01背包问题的多种求解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 01背包(动态规划,贪心算法,回溯法,分支限界法)

    01背包(动态规划,贪心算法,回溯法,分支限界法)

    有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和? number=4,capacity=8 物品编号(i) W(体积) V(价值) 1 2 3 2 3 4 3 4 5 4 5 6 1.什么是动态规划 1.动态规划算法是通过拆分问题,定义问题状态和状态之间的关系, 使得

    2024年02月08日
    浏览(13)
  • 01背包问题三种解决(贪心动态规划分支限界)

    01背包问题三种解决(贪心动态规划分支限界)

    一、实验目的 1、深入理解背包相关问题。 2、能正确设计相应的算法,解决实际问题。   3、掌握算法时间复杂度分析。 二、实验要求 用3种方法求解0-1背包问题(贪心算法、 动态规划、分支限界法 ),获得精确最优解或近似最优解均可。 通过一个规模较大的实例比较不同

    2024年02月02日
    浏览(7)
  • 贪心算法——背包问题

    14天阅读挑战赛 目录 1.题目描述      2.问题分析 3.算法设计 4.C++程序

    2023年04月18日
    浏览(12)
  • 【算法-贪心】分数背包问题

    【算法-贪心】分数背包问题

    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老 导航 檀越剑指大厂系列:全面总

    2024年02月08日
    浏览(7)
  • 贪心算法解决背包问题和动态规划解决0-1背包问题(c语言)

    贪心算法解决背包问题和动态规划解决0-1背包问题(c语言)

    运行结果如下: 运行结果如下: 总结: 贪心算法: 每一步都做出当时看起来最佳的选择,也就是说,它总是做出局部最优的选择。 贪心算法的设计步骤: 对其作出一个选择后,只剩下一个子问题需要求解。 证明做出贪心选择后,原问题总是存在最优解,即贪心选择总是安

    2024年02月04日
    浏览(12)
  • 背包问题算法全解析:动态规划和贪心算法详解

    背包问题算法全解析:动态规划和贪心算法详解

    计算机背包问题是动态规划算法中的经典问题。本文将从理论和实践两个方面深入探讨计算机背包问题,并通过实际案例分析,帮助读者更好地理解和应用该问题。 背包问题是一种经典的优化问题。有的时候我们需要将有一堆不同重量或者体积的物品放入背包,但是背包容量

    2024年02月09日
    浏览(7)
  • 【趣学算法】Day3 贪心算法——背包问题

    【趣学算法】Day3 贪心算法——背包问题

    14天阅读挑战赛 努力是为了不平庸~ 算法学习有些时候是枯燥的,这一次,让我们先人一步,趣学算法!  ❤️一名热爱Java的大一学生,希望与各位大佬共同学习进步❤️ 🧑个人主页:@周小末天天开心 各位大佬的点赞👍 收藏⭐ 关注✅,是本人学习的最大动力 感谢! 📕该

    2024年02月02日
    浏览(10)
  • (C语言贪心算法)0/1背包问题

    (C语言贪心算法)0/1背包问题

    已知一个载重为M的背包和n件物品,物品编号从0到n-1。第i件物品的重量为 wi,若将第i种物品装入背包将获益pi,这里,wi0,pi0,0=in。所谓0/1背包问题是指在物品不能分割,只能整件装入背包或不装入的情况下,求一种最佳装载方案使得总收益最大。 第 1 行中有 2 个正整

    2024年02月08日
    浏览(12)
  • c++—0/1背包问题--贪心算法(详解)

    c++—0/1背包问题--贪心算法(详解)

    贪心算法的基本思想 •贪心算法的特点是每个阶段所作的选择都是局部最优的,它期望通过所作的局部最优选择产生出一个全局最优解。 贪心与动态规划: 与动态规划不同的是,贪心是 鼠目寸光 ; 动态规划是 统揽全局 。 贪心:每个阶段产生的都是局部最优解 贪心算法的

    2024年02月04日
    浏览(9)
  • 【程序设计竞赛算法】背包问题——贪心法

    贪心算法是一种基于贪心策略的算法,它在每一步选择中都采取当前状态下的最优选择,以期望最终达到全局最优解。 背包问题是一个经典的组合优化问题,可以分为 0-1 背包问题和分数背包问题。其中,0-1 背包问题要求物品只能选择一次,而分数背包问题允许物品被选择多

    2024年02月03日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包