动态规划01背包练习

01背包的题目:

416. 分割等和子集

1049. 最后一块石头的重量 II

494. 目标和

474. 一和零


416. 分割等和子集


类加所有数字为sum,如果sum为奇数返回false
然后试着将所有数字分成两份,如果其中有一份能达到sum/2 ,返回true,否则为false。

DFS, 暴力过不了所有的点

    public static boolean canPart( int[] nums ) {int sum = 0;for ( Integer i : nums ) {sum += i;}return dfs( nums, 0, 0, sum );}private static boolean dfs( int[] nums, int index, int sum, int target ) {//base caseif ( nums.length == index ) {if ( sum == target ) {return true;} else {return false;}}//对于任意一个数,可与选或者不选return dfs( nums, index + 1, sum + nums[index], target )||dfs( nums, index + 1, sum, target );}
//    作者:winlsr
//    链接:https://leetcode-cn.com/problems/partition-equal-subset-sum/solution/dfs-dfs-bei-wang-lu-01bei-bao-dong-tai-g-4j1t/
//    来源:力扣(LeetCode)
//    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

暴力+记忆化搜索

 // 备忘录:也可用一个二维数组,一维表示元素和sum,一维表示当前索引indexprivate Map<String, Boolean> map = new HashMap<>();private boolean dfsAndMap( int[] nums, int index, int sum, int target ) {if ( nums.length == index ) {if ( sum == target ) {return true;} else {return false;}}//描述一个子问题的两个变量是 sum 和 index,组成 key 字符串String key = sum + "&" + index;if ( map.containsKey( key ) ) {return map.get( key );}boolean ret = dfs( nums, index + 1, sum + nums[index], target ) ||dfs( nums, index + 1, sum, target );map.put( key, ret );return ret;}

动态规划

等价关系是这样的:
从 [0…i] 这个区间里抽出若干个元素能够填满 sum / 2 的背包,
就一定可以把区间为全部、和为 sum 的整数拆分成两个相等的子集【1】【2】

dp[ i ][ j ] 的意思是,选 i 个数字,刚好等于 j
因此dp [ i ] [ j ]有两种状态,true或者false。

    public boolean canPartition(int[] nums) {int sum = 0;for (int num : nums) {sum += num;}if (sum % 2 == 1) {return false;}int target = sum / 2;int n = nums.length;boolean[][] dp = new boolean[n + 1][target + 1];dp[0][0] = true;for(int i=1;i<=n;i++){for(int j=1;j<=target;j++){// 不选,则当前状态和上一层状态相同if(j < nums[i-1]){dp[i][j]=dp[i-1][j];}else{// 选了当前元素, 上一层布尔值 || 选了当前元素的布尔值 dp[i][j]=dp[i-1][j] || dp[i-1][j-nums[i-1]];}}}return dp[n][target];}

一维优化

        public boolean canPartition(int[] nums) {int sum = 0;for (int num : nums) {sum += num;}if (sum % 2 == 1) {return false;}int target = sum / 2;int n = nums.length;boolean[] dp = new boolean[target + 1];dp[0] = true;for(int i=1;i<=n;i++){for(int j=target;j>=nums[i-1];j--){dp[j]= dp[j-nums[i-1]] || dp[j];}}return dp[target];}

1049. 最后一块石头的重量 II

动态规划

class Solution {public int lastStoneWeightII(int[] stones) {int sum = 0;for (int s : stones) {sum += s;}int target = sum / 2;//初始化,dp[i][j]为可以放0-i物品,背包容量为j的情况下背包中的最大价值int[][] dp = new int[stones.length][target + 1];//dp[i][0]默认初始化为0//dp[0][j]取决于stones[0]for (int j = stones[0]; j <= target; j++) {dp[0][j] = stones[0];}for (int i = 1; i < stones.length; i++) {for (int j = 1; j <= target; j++) {//注意是等于if (j >= stones[i]) {//不放:dp[i - 1][j] 放:dp[i - 1][j - stones[i]] + stones[i]dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - stones[i]] + stones[i]);} else {dp[i][j] = dp[i - 1][j];}}}// System.out.println(dp[stones.length - 1][target]);return (sum - dp[stones.length - 1][target]) - dp[stones.length - 1][target];}
}

494. 目标和

DFS 搜索

    int res = 0;public int findTargetSumWaysByDFS( int[] nums, int target ) {int sum = 0;for ( Integer i : nums ) {sum += i;}if ( sum < target ) {return 0;}dfs( nums, target, 0, 0 );return res;}public void dfs( int[] nums, int target, int sum, int index ) {if ( index == nums.length ) {if ( sum == target ) {res++;return;}}if ( index != nums.length ) {dfs( nums, target, sum - nums[index], index + 1 );dfs( nums, target, sum + nums[index], index + 1 );}}

DFS 方法二

class Solution {public int findTargetSumWays(int[] nums, int t) {return dfs(nums, t, 0, 0);}int dfs(int[] nums, int t, int u, int cur) {if (u == nums.length) {return cur == t ? 1 : 0;}int left = dfs(nums, t, u + 1, cur + nums[u]);int right = dfs(nums, t, u + 1, cur - nums[u]);return left + right;}
}
作者:AC_OIer
链接:https://leetcode-cn.com/problems/target-sum/solution/gong-shui-san-xie-yi-ti-si-jie-dfs-ji-yi-et5b/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

二维动态规划

目标和:给数组里的每个数字添加正负号得到target
数组和sum,目标和targer,
数字可以分为两堆,左边组合 x , 右边组合 y ,

x + y = sum , x - y = targer ,
那么
x + x = sum + targer
x = ( target + sum ) / 2 【3】

target是固定的,sum是固定的,y 就可以求出来
此时问题就是在集合nums中找出和为x的组合。

也就是说问题有解需要满足两个条件

  1. 数字全部加起来大于 target
  2. (sum + target) % 2 != 0 要不然无法找到相应的左右组合使得题意成立。

定义dp[ i ] [ j ]
表示, 选 0-i 个数,恰好使得他们的和为 j 的方法数有 dp[ i ] [ j ] 种。
初试化 dp[ 0 ] [ 0 ] = 1 表示一个数都不选,他们的和恰好为0 的方法数有 1 种

对于第i个数字,我们有两种选择:

  1. 选择将第 i 个数字放入左边的组合,
    此时,数字还剩 i - 1 个,背包的容量需要减去nums [ i ] (此处相当于要凑 j ,还差 j-nums[i] , 而这个信息在 dp [ i - 1 ] [ j - nums [ i ] ] 存放着)

    递推式为 dp [ i ] [ j ] = dp [ i - 1 ] [ j - nums [ i ] ]

  2. 选择放弃第i个数字,直接来到第i - 1个数字,
    那么能满足和为 j 的方式就是上一行的值(dp[ i - 1] [ j ]

    递推式为 dp [ i ] [ j ] = dp [ i - 1 ] [ j ]

  3. 当背包的容量小于第i个数字时,即j< nums[ i ],无法将第i个数字放入背包,只能跳过,递推式同2 【4】

此处相当于,剩下要凑的 数字 j 已经比 其他数字小了,无法
所以 dp [ i ] [ j ] = dp [ i - 1 ] [ j ]

public int findTargetSumWays( int[] nums, int target ) {int res = 0;int sum = 0;for ( int i : nums ) {sum += i;}if ( Math.abs( target ) > sum || (sum + target) % 2 != 0 ) {return 0;}int mid = (sum + target) / 2;int N = nums.length;int[][] dp = new int[N + 1][mid + 1];dp[0][0] = 1;for ( int i = 1; i <= N; i++ ) {for ( int j = 0; j <= mid; j++ ) {if ( j >= nums[i - 1] ) {// 两种选择的结果之和dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i - 1]];} else {// 背包的空间不足,只能选择不装物品 idp[i][j] = dp[i - 1][j];}}}return dp[N][mid];}

一维优化

    public int findTargetSumWays(int[] nums, int target) {int res = 0;int sum = 0;for (int i : nums) {sum += i;}if (Math.abs(target) > sum || (sum + target ) % 2 != 0 ) {return 0;}int mid =  (sum + target) / 2;int N = nums.length;int []dp = new int [mid+1];dp[0]=1;for (int i = 1; i <= N; i++) {for (int j = mid; j>=nums[i-1]; j--) {dp[j] = dp[j] + dp[j-nums[i-1]];}}return dp[mid];}

474. 一和零

暴力超时

int res = 0 ;    public int findMaxForm(String[] strs, int m, int n) {List<String> path = new ArrayList<>();get(strs,0,m,n,0,0,path);return res;}public void get(String[] strs,int index, int m, int n,int numM,int numN,List<String> path  ){if(numM <=m && numN<= n){res = Math.max(res,path.size());}else{return;}for(int i=index;i<strs.length;i++){path.add(strs[index]);int[] cur = count(strs[i]);get(strs,i+1,m,n,cur[0]+numM,cur[1]+numN,path);path.remove(path.size()-1);}}public int[] count(String s){int [] res = new int[2];int i = 0;int len = s.length();while(i<len){if(s.charAt(i) == '0'){res[0]++;}else{res[1]++;}i++;}return res;}

动态规划

参考【5】

public class Solution {public int findMaxForm(String[] strs, int m, int n) {int len = strs.length;int[][][] dp = new int[len + 1][m + 1][n + 1];for (int i = 1; i <= len; i++) {// 注意:有一位偏移int[] count = countZeroAndOne(strs[i - 1]);for (int j = 0; j <= m; j++) {for (int k = 0; k <= n; k++) {// 先把上一行抄下来dp[i][j][k] = dp[i - 1][j][k];int zeros = count[0];int ones = count[1];if (j >= zeros && k >= ones) {dp[i][j][k] = Math.max(dp[i - 1][j][k], dp[i - 1][j - zeros][k - ones] + 1);}}}}return dp[len][m][n];}private int[] countZeroAndOne(String str) {int[] cnt = new int[2];for (char c : str.toCharArray()) {cnt[c - '0']++;}return cnt;}
}

空间优化

public class Solution {public int findMaxForm(String[] strs, int m, int n) {int[][] dp = new int[m + 1][n + 1];dp[0][0] = 0;for (String s : strs) {int[] zeroAndOne = calcZeroAndOne(s);int zeros = zeroAndOne[0];int ones = zeroAndOne[1];for (int i = m; i >= zeros; i--) {for (int j = n; j >= ones; j--) {dp[i][j] = Math.max(dp[i][j], dp[i - zeros][j - ones] + 1);}}}return dp[m][n];}private int[] calcZeroAndOne(String str) {int[] res = new int[2];for (char c : str.toCharArray()) {res[c - '0']++;}return res;}
}

【1】https://leetcode-cn.com/problems/partition-equal-subset-sum/solution/0-1-bei-bao-wen-ti-xiang-jie-zhen-dui-ben-ti-de-yo/782571
【2】https://leetcode-cn.com/problems/partition-equal-subset-sum/solution/0-1-bei-bao-wen-ti-xiang-jie-zhen-dui-ben-ti-de-yo/
【3】https://leetcode-cn.com/problems/partition-equal-subset-sum/solution/yi-pian-wen-zhang-chi-tou-bei-bao-wen-ti-a7dd/
【4】https://leetcode-cn.com/problems/target-sum/solution/hen-xiang-xi-de-zhuan-hua-wei-0-1bei-bao-irvy/
【5】https://leetcode-cn.com/problems/ones-and-zeroes/solution/dong-tai-gui-hua-zhuan-huan-wei-0-1-bei-bao-wen-ti/

【随想录12】01背包练习相关推荐

  1. 代码随想录42——动态规划:0-1背包理论基础、0-1背包滚动数组、416分割等和子集

    文章目录 1.0-1背包理论基础 1.1.概述 1.2.0-1背包 1.3.二维dp数组01背包--动规五部曲 1.4.完整测试代码 2.0-1背包滚动数组 2.1.一维滚动数组 2.2.一维dp数组 ...

  2. Dream City(01背包+小贪心)acm寒假集训日记21/12/30

    题目如下: AC代码如下: #include<iostream> #include<algorithm> #include<cstring> #include< ...

  3. NYOJ 860 又见01背包

    有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W  的物品,求所有挑选方案中物品价值总和的最大值. 1 <= n <=100 1 <= wi < ...

  4. hdu 3449 Consumer 01背包

    http://acm.hdu.edu.cn/showproblem.php?pid=3449 这个题AC的有点稀里糊涂(是1A过的),采用的01背包的方法: 思路:定义了两个数组用来存储最终结果和但购 ...

  5. hdu 3732(01背包转多重背包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3732 思路:这么大的数据,用01背包肯定会TLE的,01背包转多重背包..最多也就11*11=121件 ...

  6. 洛谷 P1049 装箱问题(01背包)

    一道水题,但看到好久没有发博客了,再一看是一道noip普及组t4,就做了. 题目链接 https://www.luogu.org/problemnew/show/P1049 解题思路 一道裸的01背包 ...

  7. 杭电1171(01背包求解)

    题目: Problem Description Nowadays, we all know that Computer College is the biggest department in HDU ...

  8. HDu 3449 (有依赖的01背包) Consumer

    题意: 有n件物品,对应有不同的价格和价值,这是典型的01背包.但现在有了一个限制,要买物品先买能装这件物品的特定的盒子,盒子的价值为0 代码理解得还不是太好,感觉这是一个"二重" ...

  9. [UVa1213]Sum of Different Primes(递推,01背包)

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

最新文章

  1. 测试 ClownFish、CYQ、Entity Framework、Moon、MySoft、NHibernate、PDF、XCode数据访问组件性能...
  2. mysql8.0最低需要多少内存_MySQL8.0内存相关参数介绍
  3. python读取文件类型_python准确判断文件类型
  4. SSH(Struts2+Hibernate+Spring)开发策略
  5. zabbix邮件发不出去
  6. WebBrowser一点心得,如果在Javascript和Winform代码之间实现双向通信
  7. Discuz! Database Error(2003) notconnect 问题解決
  8. Java 高效编程之 Builder 模式
  9. 虚拟机克隆后修改网络部分
  10. Excel实验情况对比排序
  11. java 生成pdf 下载_java生成PDF,并下载到本地
  12. 华硕h410csm怎么开启_华硕主板怎么开启uefi模式?华硕主板BIOS开启uefi模式详细方法...
  13. Ubuntu 16.04安装sogou拼音输入法
  14. 大白菜u盘制作工具教程
  15. 常用网络测试软件,常用的网络故障检测工具有哪些
  16. SAP_FI统驭科目
  17. 淘宝网 286亿海量图片存储与处理架构
  18. 微信版QQ群助手 | 微信也可以折叠群聊了
  19. 上海市建平中学2021年高考成绩查询,2021年上海市高中排名一览表
  20. 黄页88网站之加密字符串破解

热门文章

  1. 全国计算机设计大赛参后感
  2. 脱壳工具:Youpk的使用详解
  3. 当Python碰上斗地主残局,该如何破解?AI对AI谁能更胜一筹?
  4. Vue.js 框架基础笔记
  5. pickle —— Python 对象序列化(python=3.8)
  6. LinuxCast学习笔记十八:Network_Basic
  7. 如何合理控制亚马逊FBA头程物流费用?
  8. 题解 CF292A 【SMSC】
  9. office -word -批量删除回车、制表符、分页符、换行符、分栏符等
  10. hexo-butterfly使用aplayer加载音乐页面