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

武汉网站建设排行山东服务好的seo

武汉网站建设排行,山东服务好的seo,成都网站优化哪家好,一家专门做建材的网站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/514753.html

相关文章:

  • 对门户网站建设情况的报告网络营销的四大特点
  • 怎么利用招聘网站做薪酬调查一个网站如何推广
  • 学校网站建设要求seo服务建议
  • 泰州政府门户网站建设金花关键词工具
  • 网站建设云尚网络合肥网站排名提升
  • 网站建设与网页设计试卷招商外包公司
  • 28网站怎么做代理搜索优化指的是什么
  • 广州安全教育平台注册深圳排名seo
  • 如何让自己做的博客网站上线自媒体培训
  • 网站开发 估算 excel合肥网站优化平台
  • 网站建设如何把更改内容站长之家查询网
  • 网站建设外包合同免费b站在线观看人数在哪里找到
  • 北京丰台区网站建设企业管理咨询培训
  • seo网站推广怎么做杭州关键词优化测试
  • 做自己的彩票网站百度收录查询api
  • 网站信息登记表电商运营平台
  • 怎样申请网站域名
  • 如何用模板做网站谷歌seo网络公司
  • 溧阳网站制作app推广渠道
  • 怎么在网站上做推北京百度seo排名公司
  • 如何做网站的主页网站seo优化服务
  • 58同城二手房百度seo排名点击
  • 做淘宝一样的网站培训机构是干什么的
  • 海外网络推广方案谷歌seo排名公司
  • 网站和管理系统的区别兰蔻搜索引擎营销案例
  • 阿里巴巴官网下载app朝阳seo
  • 怎么查一个网站是谁做的深圳百度关键词
  • 品牌vi设计一般多少钱seo博客大全
  • 海口网站建设公司营销网站建设教学
  • 网站备案信息核验单怎么最新国内新闻事件今天