当前位置: 首页 > wzjs >正文

装修合同电子版推广优化排名

装修合同电子版,推广优化排名,网站帮助,凡科自助建站自己做网站0-1背包:有n个物品,第i个物品的体积为w[i],价值为v[i],每个物品至多选择一个,求体积和不超过capacity的最大价值和。 对于第i个物品,我们只有两种选择:选,或者不选。如果选&#xf…

0-1背包:有n个物品,第i个物品的体积为w[i],价值为v[i],每个物品至多选择一个,求体积和不超过capacity的最大价值和。

对于第i个物品,我们只有两种选择:选,或者不选。如果选,那么背包的剩余容量减少w[i].如果不选,那么背包的剩余容量不变。

而问题实际上是:在剩余容量为c时,从前i个物品中得到的最大价值和为多少?

根据分析,我们可以进一步拆分这个问题。如果不选,那么子问题就为:在剩余容量为c时,从前i-1个物品中得到的最大价值和为多少?如果选,那么子问题就为:在剩余容量为c-w[i]时,从前i-1个物品中得到的最大价值和为多少?

显然可以用动态规划了。

第一步:确定dp数组的意思:dp[i][j]表示:从第0-i种物品中挑选,放进容量为j的背包里,得到的最大价值和。

第二步:初始化dp数组(对边界情况进行处理):当背包容量为0时,无法装下物品,因此价值为0,由此可令dp[i][0]==0;当选择物品的范围为0-0时,意味着我们只能选第一个物品,那么最大价值和只能为v[0],由此可令dp[0][i]==v[0].

第三步:填充。由上可知,要么选,要么不选。但是我们不能忘记选择权从何而来:背包的剩余容量大于等于物品体积。如果不是,那么直接不选。如果是,那么就根据前面的分析进一步处理。如果不选则dp[i][j]=dp[i-1][j].如果选,那么dp[i][j]=dp[i][j-w[i]]+v[i].选择二者中的最大值即可。

int backpack01(int kinds, int capacity, vector<int>& w, vector<int>& v)
{//kinds表示物品数量,capacity表示背包总容量,w[i]表示第i+1个物品的体积,v[i]表示第i+1个物品的价值vector<vector<int>>dp(kinds, vector<int>(capacity + 1, 0));//初始化://1.背包容量为0时,无法装下物品,最大价值和为0for (int i = 0; i < kinds; i++){dp[i][0] = 0;}//2.只有一种物品时,只能选择第一个物品,最大价值和为v[0]for (int i = 0; i <= capacity; i++){dp[0][i] = v[0];}//填充for (int i = 1; i < kinds; i++)//物品编号{for (int j = 1; j <= capacity; j++)//背包剩余容积{if (j < w[i]) dp[i][j] = dp[i - 1][j];//容不下当前物品,只能不选else{dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]);}}}return dp[kinds - 1][capacity];
}

我们发现,dp[i][?]只与dp[i-1][?]有关,因此我们可以对空间复杂度进行优化,用一个一维数组dp滚动处理即可。

int backpack01(int kinds, int capacity, vector<int>& w, vector<int>& v)
{vector<int>dp(capacity + 1, 0);//dp[i]表示:背包容量为i时里面物品的最大价值和dp[0] = 0;//背包容量为0,装不下物品,最大价值和为0for (int i = 0; i < w.size(); i++)//外层循环:控制某一种物品{for (int j = capacity; j >= w[i]; j--)//内层循环:对于该种物品进行处理{dp[j] = max(dp[j], dp[j - w[i]] + v[i]);}}return dp[capacity];
}

关键点:j从capacity开始倒着处理。为什么要倒着处理?实际上,我们可以用“双数组”的理念去理解(双数组滚动也可以,只不过单数组空间复杂度更优,用双数组滚动更容易想象)。我们退化成两个数组,数组a用来保存上一轮的dp值,数组b用来填充接下来的dp值。前面我们说过,dp[i][x]实际上只由dp[i-1][x]决定,所以填充b只需要依赖a中的值。但也正因如此,我们在填充b的时候,就不能改变a中的值了。我们现在只有一个数组,如果我们从前往后处理,那么相当于:我们在填充b中dp值时,它所依赖的a中的dp值已经被改变了。所以我们需要从后往前处理,因为填充依赖前面的原始数据。两个关键词:前面的+原始。

同时我们还进行了一点优化:j>=w[i].这意味着我们不需要再判断当前背包的容量是否能够装下物品了,因为这时候物品已经定下来了(外层循环控制)。所以小于w[i]的j必然都装不下,就不用处理了。

看一道具体的题目:

2915. 和为目标值的最长子序列的长度 - 力扣(LeetCode)

本题中:下标相当于物品编号,下标对应的值相当于物品的体积,target相当于背包的容量,长度相当于价值。

int lengthOfLongestSubsequence(vector<int>& nums, int target)
{if (accumulate(nums.begin(), nums.end(), 0) < target) return -1;int kinds = nums.size(), capacity = target;vector<int>dp(capacity + 1, -1);dp[0] = 0;for (int i = 0; i < kinds; i++){for (int j = capacity; j >= nums[i]; j--){if (dp[j - nums[i]] != -1)//注意这里{dp[j] = max(dp[j], dp[j - nums[i]] + 1);}}}return dp[capacity];
}

为什么需要判断dp[j-nums[i]]是否等于-1?

我们先来想想等于-1意味着什么。dp[j-nums[i]]==-1意味着:在考虑前i个元素时,无法组成和为j-nums[i]的子序列。而只有当存在j-nums[i]的子序列时,我们才能通过添加当前元素nums[i]来得到和为j的子序列。

因此,如果dp[j-nums[i]]等于-1,那意味着没有基础来构建dp[j],所以不能更新。

http://www.dtcms.com/wzjs/108287.html

相关文章:

  • 甘肃省住房和城乡建设厅网站职称证查询站群seo技巧
  • 商务网站设计实训报告淘宝seo是指什么
  • 政府网站设计案例seo外包如何
  • 网站服务器租用 配置企业网络营销策略
  • 农安县住房城乡建设局网站洛阳市网站建设
  • 做网站切图软件星链友店
  • 南京历史文化网页设计北京seo网络推广
  • 建设物流谷歌搜索引擎优化seo
  • 鼓楼徐州网站开发营销失败案例分析
  • 博客园wordpress模板搜索引擎seo关键词优化方法
  • 移动端网站制作杭州seo运营
  • 个人做网站流程近期国内新闻热点事件
  • 车公庙网站建设如何建立网站服务器
  • 京东商城网站怎么做营业推广方式
  • 云南企业网站建设地推一手项目平台
  • 进一步网站建设app投放渠道有哪些
  • 重庆做网站哪个好些嘛批量优化网站软件
  • win7下asp.net网站发布参考消息今天新闻
  • 广告联盟做网站无锡网站建设优化公司
  • 网站开发能进无形资产吗南京seo关键词排名
  • 网站服务器多少钱一年香港头条新闻
  • 聊城做网站的公司信息网站怎么开发
  • 巫溪集团网站建设兰州百度推广的公司
  • 沧州wap网站制作十大最靠谱教育培训机构
  • 福州网站设计哪家比较好关键词优化是怎么弄的
  • 济宁网站建设 中企动力临沂南通seo网站优化软件
  • 网页游戏 手机铁力seo
  • 深圳方维网站设计公司全国最新实时大数据
  • git怎么做隐私政策网站南宁网站seo排名优化
  • 安全狗iis 网站css无法访问石家庄seo