1. 问题描述:

有一堆石头,每块石头的重量都是正整数。每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y - x。
最后,最多只会剩下一块石头。返回此石头最小的可能重量。如果没有石头剩下,就返回 0。

示例:

输入:[2,7,4,1,8,1]
输出:1
解释:
组合 2 和 4,得到 2,所以数组转化为 [2,7,1,8,1],
组合 7 和 8,得到 1,所以数组转化为 [2,1,1,1],
组合 2 和 1,得到 1,所以数组转化为 [1,1,1],
组合 1 和 1,得到 0,所以数组转化为 [1],这就是最优值。

提示:

1 <= stones.length <= 30
1 <= stones[i] <= 1000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/last-stone-weight-ii

2. 思路分析:

分析题目可以知道我们可以将两堆石子分为正数和负数的石子,我们是希望这两堆石子在拿出来之后剩余的差值是最小的,所以我们尽可能需要使得两堆石头的差值是最小的,两堆石头的重量越接近差值肯定是最小的,所以我们可以将全部石头分成两堆石头并且使得两堆石头的重量尽可能接近sum // 2(这样最后的剩余石头的重量才是最小的),经过若干次的粉碎剩下来的就是这两堆石头的差值,这个时候原问题就可以转化为零一背包的问题,当前背包的容量为sum // 2,价值为石头的重量,我们需要求解的是在背包容量为sum // 2前提下装满背包的最大价值(这一点是核心,想到零一背包模型剩下来的就比较好办了);使用传统的零一背包模型就可以解决,尝试将当前的石头放入到容量从j = sum // 2的背包到j - stones[i]的背包中(使用两层循环第一层循环枚举所有的石头,第二层循环枚举当前背包的体积);零一背包问题的一维状态转移方程为:dp[j] = max(dp[j],dp[j - v] + w),v = stones[i],w = stones[i],因为这里使用的是一维数组所以在第二层枚举体积的时候需要逆序遍历(二维数组可以按顺序遍历),这样可以保证dp[j]和dp[j - v]都是上一层循环对应的状态。

3. 代码如下:

from typing import Listclass Solution:def lastStoneWeightII(self, stones: List[int]) -> int:s = sum(stones)dp = [0] * (s // 2 + 1)for i in range(len(stones)):for j in range(s // 2, stones[i] - 1, -1):dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])# 返回两堆石子的差值: s - dp[j] - dp[j], python列表中索引为-1表示的是最后一个元素return s - 2 * dp[-1]

1049 最后一块石头的重量 II(零一背包问题)相关推荐

  1. day43|● 1049. 最后一块石头的重量 II ● 494. 目标和 ● 474.一和零

    1049. 最后一块石头的重量 II 1.代码 class Solution { public:int lastStoneWeightII(vector<int>& stones) ...

  2. day36|1049. 最后一块石头的重量 II、494. 目标和、474.一和零

    1049. 最后一块石头的重量 II 有一堆石头,用整数数组 stones 表示.其中 stones[i] 表示第 i 块石头的重量. 每一回合,从中选出任意两块石头,然后将它们一起粉碎.假设石头的重 ...

  3. 【43天|1049. 最后一块石头的重量 II ● 494. 目标和 ● 474.一和零 】

    1049. 最后一块石头的重量 II dp[j] 表示j容量的背包可以背下石头的最大重量. class Solution {public:int lastStoneWeightII(vector< ...

  4. LeetCode:1049.最后一块石头的重量II 494.目标和 474.一和零

    1049.最后一块石头的重量II 题目 有一堆石头,用整数数组 stones 表示.其中 stones[i] 表示第 i 块石头的重量. 每一回合,从中选出任意两块石头,然后将它们一起粉碎.假设石头的 ...

  5. 代码随想录刷题|LeetCode 1049. 最后一块石头的重量II 494. 目标和 474.一和零

    目录 1049. 最后一块石头的重量 II 思路 最后一块石头的重量|| 494. 目标和 思路 0.求什么 1.确定dp数组的含义 2.递推公式 3.初始化dp数组 4.遍历顺序 目标和 474.一 ...

  6. LeetCode刷题day43|1049. 最后一块石头的重量 II、 494. 目标和、474.一和零

    文章目录 一.1049. 最后一块石头的重量 II 二.494. 目标和 三.474.一和零 一.1049. 最后一块石头的重量 II 这道题其实就与"分割子集"一样,就是先将总和 ...

  7. 代码随想录算法训练营day42 |动态规划之背包问题 11.分割等和子集 1049. 最后一块石头的重量 II 494. 目标和

    day42 11.分割等和子集 1.dp数组的含义 2.确定递推公式 3.dp数组初始化 4.确定遍历顺序 5.打印dp数组 1049. 最后一块石头的重量 II 1.确定dp数组以及下标的含义 2. ...

  8. LeetCode-动态规划背包题-1049. 最后一块石头的重量 II

    描述 1049. 最后一块石头的重量 II 有一堆石头,用整数数组 stones 表示.其中 stones[i] 表示第 i 块石头的重量. 每一回合,从中选出任意两块石头,然后将它们一起粉碎.假设石 ...

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

    1049. 最后一块石头的重量 II 无论按照何种顺序粉碎石头,最后一块石头的重量总是可以表示成 可以这样理解,将所有的石头分为两堆,ki=1的石头是一堆,ki=-1的石头是另一堆,我们的目标就是求上 ...

  10. 153、【动态规划】leetcode ——1049. 最后一块石头的重量 II:滚动数组(C++版本)

    题目描述 原题链接:1049. 最后一块石头的重量 II 解题思路 本题要找的是最小重量,我们可以将石头划分成两个集合,当两个集合的重量越接近时,相减后,可达到的装量就会是最小,此时本题的思路其实就类 ...

最新文章

  1. 大数据安全事件警示:海量数据放哪才真正放心
  2. python官网怎么下载安装-Python怎么下载安装
  3. 重启IIS报错:IIS 服务或万维网发布服务,或者依赖这 服务可能在启动期间发生错误或者已禁用...
  4. matlab 现代信号处理,The-first-matlab-exercise 清华大学张旭东老师现代信号处理第一次matlab习题 - 下载 - 搜珍网...
  5. GDCM:dicom文件转储签证变更的测试程序
  6. 闲谈“个人核心竞争力”与“危机感” !!!
  7. 复习--SQL Server (一) -系统数据库
  8. python类定义的讲解_python面向对象、自定义类等使用实例讲解
  9. postgres主从配置
  10. Java面试题:热情盛夏,分享Java大厂面试百题
  11. codeforces776D
  12. element tree不刷新视图_安卓从入门到进阶第五章(视图查看)
  13. Radon变换理论介绍
  14. 编程数学读书笔记 -- 第二章逻辑
  15. 在windows系统中安装显卡驱动
  16. 目前重庆橱柜市场分析
  17. vue使用vue-video-player播放视频及遇到的问题
  18. html手机qq登陆验证码,为什么qq登陆需要验证码?qq登陆需要验证码怎么取消?...
  19. 光纤快速连接器如何安装使用?与冷接子有何区别?
  20. 网站制作教程是什么?这些步骤要知道

热门文章

  1. 远瑞服务器无影响,泰拉瑞亚加mod之后如何搭建服务器联机
  2. OpenCV字符识别
  3. Android平台GB28181接入端如何对接UVC摄像头?
  4. Linux没有fstab文件,Linux配置文件fstab
  5. 事情很严重,卡巴斯基很生气
  6. 会计计算机敲打大赛,老会计的办公史 从打算盘到敲键盘
  7. CocosCreator Lerp线性插值
  8. SpringMVC(一)MVC设计模式
  9. 软件测试面试技巧 这么准备,拿下心仪offer不是问题
  10. html设置相对定位代码怎么写,Web前端面试题第八道—绝对定位与相对定位