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

专业做网站排名的人北京搜索引擎推广服务

专业做网站排名的人,北京搜索引擎推广服务,青岛做网站建设多少钱,长沙招聘网58同城招聘发布二维 有n件物品和一个最多能背重量为w的背包。第i件物品的重量是w[i],得到的价值是v[i]。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。 1.确定dp数组以及下标的含义: dp[i][j]表示从下标为[0~i]的物品里任意取&#xf…

二维

有n件物品和一个最多能背重量为w的背包。第i件物品的重量是w[i],得到的价值是v[i]。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。

1.确定dp数组以及下标的含义:

dp[i][j]表示从下标为[0~i]的物品里任意取,放进容量为j的背包,能得到最大的价值。

2.确定递推公式:

对于dp[i][j]有两种情况:放物品i;不放物品i。

如果不放物品i,dp[i][j]=dp[i-1][j];

如果放物品i,那么背包要先留出物品i的容量,背包容量变为j-w[i],所以dp[i][j]=dp[i-1][j-w[i]]+v[i]。

所以递推公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i])

3.初始化:

首先如果背包容量j为0的话,背包价值一定为0,也就是dp[i][0]=0。

由递推公式可以看出i是由i-1推导出来的,那么i为0的时候就一定要初始化。所以当j<w[0]时,dp[0][j]=0;当j>=w[0]时,dp[0][j]=v[0]。

for (int i = 1; i < w.length; i++) {  // 当然这一步,如果把dp数组预先初始化为0了,这一步就可以省略dp[i][0] = 0;
}
for (int j = w[0]; j <= bagweight; j++) {dp[0][j] = v[0];
}

4.确定遍历顺序:

有两个维度的遍历:物品与背包重量。

先遍历物品,然后再遍历背包重量:

for (int i = 1; i < n; i++) {for (int j = 0; j <= bagweight; j++) {if (j < weight[i]) {dp[i][j] = dp[i - 1][j];} else {dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);}}}

5.举例推导dp数组:

 

一维

1.确定dp数组以及下标的含义:

dp[j]表示容量为j的背包所背的物品价值最大可以为dp[j] 。

2.确定递推公式:

二维dp数组的递推公式为:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i])。可以发现如果把dp[i-1]那一层拷贝到dp[i]上,表达式完全可以是:dp[i][j] = max(dp[i][j], dp[i][j - w[i]] + v[i])

所以可以把i这个维度去掉,也就是:dp[j] = max(dp[j], dp[j - w[i]] + v[i])

3.初始化:默认都初始化为0即可。

4.确定遍历顺序:

先遍历物品,再遍历背包容量:

for (int i = 0; i < n ; i++) {for (int j = bagweight ; j >= w[i]; j--) {dp[j] = Math.max(dp[j], dp[j - w[i]] + v[i]);}}

这里可以看出,一维dp遍历背包是从大到小遍历的,这和二维dp遍历不同,为什么?

如果背包正序遍历,物品i可能被放入多次。

比如:物品0的重量weight[0] = 1,价值value[0] = 15,如果正序遍历:

dp[1] = dp[1 - w[0]] + v[0] = 15

dp[2] = dp[2 - w[0]] + v[0] = 30

那么物品0就被放入了两次,所以不能正序遍历。

而倒序遍历:

dp[2] = dp[2 - w[0]] + v[0] = 15 (dp数组已经都初始化为0)

dp[1] = dp[1 - w[0]] + v[0] = 15

这样就能保证每种物品只取一次。

而二维dp遍历不需要倒序是因为dp[i][j]都是通过上一层dp[i-1][j]计算而来的,本层的dp[i][j]是不会被覆盖的。

5.举例推导dp数组:还是之前的例子

LeetCode 416 分割等和子集

题目链接: 416. 分割等和子集 - 力扣(LeetCode)

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

示例 1:

输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。
示例 2:

输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。

首先求出nums数组的元素和ans,如果ans为奇数,直接返回false即可。 

 nums数组相当于0/1背包问题中的容量数组和价值数组,判断能否将nums数组分割成链各个元素和相等的自己,那就相当于判断能否将容量为ans/2的背包装满。

因为容量和价值是相等的,所以最后容量为ans/2的背包的最大价值为ans/2,说明能装满,返回true,否则返回false。本质和0/1背包问题是一样的。

代码如下:

class Solution {public boolean canPartition(int[] nums) {int ans=0;int n=nums.length;for(int i=0;i<n;i++)ans+=nums[i];if(ans%2==1)return false;int[] dp=new int[ans/2+1];for(int i=0;i<n;i++){for(int j=ans/2;j>=nums[i];j--){dp[j]=Math.max(dp[j],dp[j-nums[i]]+nums[i]);}}if(dp[ans/2]==ans/2)return true;else return false;}
}
http://www.dtcms.com/a/473245.html

相关文章:

  • wordpress适合下载站的主题国外购物网站app
  • php网站开发实例教程简介寮步做网站公司
  • 营销网站建设推广安徽省工程建设信息网职称查询
  • 摄影网站网址大全app电商网站
  • 信阳网站建设找汉狮建筑网站大全免费
  • 北京建设工程网站小程序软件开发制作
  • 下载网站备案的核验单网站历史快照
  • 2018年公司网站建设费分录国外的设计网站app吗
  • 网站怎么建立视频网站商城开发公司
  • 舟山网站建设重庆做企业网站设计的公司
  • 易做文学网站的logo网站功能定制合同
  • 铁岭做网站一般多少钱优良的网站邮箱服务器提供商isp
  • 单位网站建设要求手机版oa办公软件
  • 国外网站加速器小仙女12777 coon域名查询
  • 海南省住房城乡建设厅网站首页苏州网页设计培训
  • wordpress主题整站wordpress重定向seo
  • 上海网站设计费用做网站一年赚多少钱
  • 四博网站备案网站开发 图片服务器
  • 个人信息网站htmlwordpress 载入慢
  • 腾博会的网站是什么腾讯企业邮箱手机版app
  • 西双版纳网站建设公司附近有木有做网站
  • 2008iis网站建设承德项目网
  • 谷歌seo网站优化伪原创嵌入网站
  • 怎么建设自己网站首页[8dvd]flash网站源文件 flash整站源码
  • 开贴纸网站要怎么做杭州网站建设设计
  • 广州网站建设泸州传销教你做网站
  • 网站建设和管理维护重庆市建设安全监督站的网站
  • 网站建设详细方案模板提供网站建设工具的品牌
  • 网站引导页面制作的四个任务名称阿里巴巴 商城网站怎么做
  • 物流公司做网站注重什么问题如何申请个人网站