D36|01背包问题+leetcode 416

01背包问题---二维

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

动态规划5步:

1、dp[i][j]:从下标[0,i]的物品里任取,放到容量为j的背包中最大的价值总和

2、递推关系:如果不让物品i,此时最大价值总和是dp[i-1][j],如果放入物品i,此时最大价值总和是dp[i-1][j-weight[i]]+value[i],所以最大价值应该是两者的最大值dp=max{dp[i-1][j],dp[i-1][j-weight[i]]+value[i]};

3、初始化:由递推关系式可以知道,dp[i][j]由其上面的数组元素或者由其左上角数组元素决定,所以需要初始化dp[0][j]与dp[i][0]的所有元素。

4、遍历顺序:i表示物品,j表示背包,无论是背包先遍历还是物品先遍历,都能满足dp[i][j]由其上面的数组元素或者由其左上角数组元素决定这一条件,同时遍历顺序为从小到大。

5、打印数组:遇到问题可以打印数组。

01背包问题---一维

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

思路:由二维求解可知,下一层的每个元素由上一层决定,所以可以用一维数组来表示,下一行未处理的数据就是上一行直接拷贝而得。

动态规划5步:

1、dp[i]:背包容量为i可装入物品价值总和最大为dp[i];

2、递推关系:如果不放入物品,此时最大价值总和为dp[i],这个表达式是从二维运算得到的在二维数组中不放物品时dp[i-1][j],根据二维转为一维的规则,所以一维的是dp[i],如果继续放入物品,最大价值总和为dp[i-1]+value[i];所以dp[i]=max{dp[i],dp[i-weigh[i]]+value[i]};

3、初始值:由递推关系可知dp[0]=0;

4、递推关系:因为此时是一维数组,所以应该先遍历物品,后遍历背包,同时因为每个物品只能放一次,所以,背包的遍历应该是由后向前遍历,不然从前向后遍历,后面的元素会使用到前面的元素,但是前面的元素已经改变了,不是上一层的元素了。

5、打印数组:在遇到问题时打印数组可以看到细节。

416. 分割等和子集

思路:

这道题如果所有元素的和为奇数,则不能等和分割。可以把nums数组当作物品,每一个元素的价值和重量都是nums[i],如果背包的最大重量为所有元素和的一半,则可以实现等和分割。

代码:

class Solution {

public:

    bool canPartition(vector<int>& nums) {

        int sum=0;

        vector<int> dp(10001,0);

        for(int i=0;i<nums.size();i++)

        {

            sum+=nums[i];

        }

        if(sum%2==1) return false;

        int target=sum/2;

        for(int i=0;i<nums.size();i++)

        {

            for(int j=target;j>=nums[i];j--)

            {

                dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);


            }

        }

        if(dp[target]==target)return true;

        return false;

    }

};

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容