Day 43 1049. 最后一块石头的重量 II 494. 目标和 474.一和零

最后一块石头重量Ⅱ

有一堆石头,每块石头的重量都是正整数。

每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 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

​ 关键点在想到:让石头尽量分成重量相同的两堆,相撞之后剩下的石头最小

​ 又因为唯一性,很自然就化解为了01背包问题;

​ 本题物品的重量为stones[i],物品的价值也为stones[i]。

​ 对应着01背包里的物品重量weight[i]和 物品价值value[i]。

​ 动规五部曲:
​ 1.dp数组含义:
​ dp[j]表示容量为j的背包,最多可以背的最大重量为dp[j];

​ 2.确定递推公式:

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

​ 3.初始化:

​ 因为提示中给出1 <= stones.length <= 30,1 <= stones[i] <= 1000,所以最大重量就是30 * 1000 。

​ 而我们要求的target其实只是最大重量的一半,所以dp数组开到15000大小就可以了。

​ 当然也可以把石头遍历一遍,计算出石头总重量 然后除2,得到dp数组的大小。

​ 我这里就直接用15000了。

​ 即vector<int> dp (15001, 0);

​ 4.遍历顺序:

​ 和之前的一致,内层倒序:

for (int i = 0; i < stones.size(); i++) { // 遍历物品
    for (int j = target; j >= stones[i]; j--) { // 遍历背包
        dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);
    }
}

​ 5.打印数组:

#include<iostream>
#include<vector>
#include<numeric>
using namespace std;
class solution {
public:
	int lastStoneWeightII(vector<int>& stones){
		int sum = accumulate(stones.begin(), stones.end(), 0);//向下取整求背包的最大空间
		int target = sum / 2;
		vector<int> dp(15001, 0);//根据测试案例调整dp数组大小
		for (int i = 0; i < stones.size(); i++) {
			cout << "The current dp array is:" << endl;
			for (int j = target; j >= stones[i]; j--) {
				dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);
			}
			for (int k = 0; k <= target; k++) {
				cout << dp[k] << ' ';
			}
			cout << endl;
		}
		return sum - 2 * dp[target];
	}
};
int main() {
	solution mySolution;
	vector<int> tests = { 2,4,1,1 };
	cout << "The result is:" << mySolution.lastStoneWeightII(tests) << endl;
	return 0;
}

目标和

给定一个非负整数数组,a1, a2, …, an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。

返回可以使最终数组和为目标数 S 的所有添加符号的方法数。

示例:

  • 输入:nums: [1, 1, 1, 1, 1], S: 3
  • 输出:5

解释:

  • -1+1+1+1+1 = 3
  • +1-1+1+1+1 = 3
  • +1+1-1+1+1 = 3
  • +1+1+1-1+1 = 3
  • +1+1+1+1-1 = 3

一共有5种方法让最终目标和为3。

提示:

  • 数组非空,且长度不会超过 20 。
  • 初始的数组的和不会超过 1000 。
  • 保证返回的最终结果能被 32 位整数存下。

​ 先不考虑是否为背包问题,先分析问题本身;其实还是可以视为一个子集划分的问题;

​ 由于数组非负,所以target = sum_plus - sum_minus其中,sum_plus + sum_minus = sum;

​ 所以sum_minus = (sum - target)/2;

​ 找这个sum_minus是否存在即可

​ 动规五部曲:

​ 1.dp数组及其下标含义:

​ dp[j]表示sum_minus为j时有dp[j]种方法使得子集和为sum_minus;

​ 2.确认递推公式:

​ 这里借用二维数组来方便理解:

​ dp[i][j] = dp[i-1][j] + dp[i-1][j -nums[i]];

​ dp[i - 1][j]是不将物品i放入背包的方式数,dp[i-1][j - nums[i]]使将物品i放入背包的方式数;

​ 再次确定此时一维dp数组含义,dp[j]指的是子集和为j的情况下的路径数:

​ 要用若干个元素组成和为j的方案数,那么有两种选择:不选第i个元素或者选第i个元素;

​ 如果不选第i个元素,那么原来已经有多少种方案数就不变;

​ 如果选第i个元素,那么就是在已有的基础上,加上剩下要组成和为j - nums[i] 的方案数就等于dp[j - nums[i]];

​ 所以,很显然,dp[j] = dp[j] + dp[j - nums[i]];

​ 3.初始化:

​ 很显然,根据上面的推导,dp[0] = 1,不然的话所有项都是0,其余dp[j] = 0;

​ 4.遍历顺序:

​ 经典一维01背包

​ 5.打印数组:
image-20240510200606342

image-20240510203829314

#include<numeric>
#include<iostream>
#include<vector>

using namespace std;

class solution {
public:
	int findTargetSumWays(vector<int>& nums, int target) {
		int sum = accumulate(nums.begin(), nums.end(), 0);
		if (abs(target) > sum)	return 0;
		if ((sum -  target) % 2 == 1)	return 0;
		int sum_minus = (sum - target) / 2;
		vector<int> dp(1001, 0);//因为初始数组和小于1000,target可取范围为-1000-1000,所以sum_minus <= 1000恒成立
		dp[0] = 1;
		for (int i = 0; i < nums.size(); i++) {
			for (int j = sum_minus; j >= nums[i]; j--) {
				dp[j] += dp[j - nums[i]];
			}
			cout << "The current dp array will be shown as below:" << endl;
			for (int k = 0; k <= sum_minus; k++) {
				cout << dp[k] << ' ';
			}
			cout << endl;
		}
		return dp[sum_minus];
	}
};

int main() {
	cout << "Please enter the test sequences(requiring non-negative integers) end with -1:" << endl;
	vector<int> tests;
	int num;
	while (cin >> num && num != -1) {
		tests.push_back(num); // 将输入的整数添加到vector中  
	}
	cout << "Please enter the target sum:" << endl;
	int target;
	cin >> target;
	solution mySolution;
	cout << "There are " << mySolution.findTargetSumWays(tests, target) << " ways to get to the target sum." << endl;
	return 0;
}

一和零

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs 的最大子集的大小,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

示例 1:

  • 输入:strs = [“10”, “0001”, “111001”, “1”, “0”], m = 5, n = 3
  • 输出:4
  • 解释:最多有 5 个 0 和 3 个 1 的最大子集是 {“10”,“0001”,“1”,“0”} ,因此答案是 4 。 其他满足题意但较小的子集包括 {“0001”,“1”} 和 {“10”,“1”,“0”} 。{“111001”} 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。

示例 2:

  • 输入:strs = [“10”, “0”, “1”], m = 1, n = 1
  • 输出:2
  • 解释:最大的子集是 {“0”, “1”} ,所以答案是 2 。

提示:

  • 1 <= strs.length <= 600
  • 1 <= strs[i].length <= 100
  • strs[i] 仅由 ‘0’ 和 ‘1’ 组成
  • 1 <= m, n <= 100

​ 看起来好像很复杂,实际上就是拥有两个维度的背包,容量分别为m和n;

​ 至于strs虽然看上去有许多重复的0 1,但是实际上每个strs[i]只能取一次,所以还是0-1背包问题;

​ 动规五部曲:
​ 1.dp数组含义及其下标:

​ dp[i][j],表示在子集在最多有m个0,n个1的前提下,最多可以选择有dp[i][j]个元素;

​ 2.递推公式:

​ 先考虑最原始的0-1背包问题:

​ dp[i][j] = max(dp[i - 1][j], dp[i][j - weight[i]] + values[i]);

​ 对于本题:

​ dp[i][j] = max(dp[i][j], dp[i - zero_nums][y - one_nums] +1);

​ 3.初始化:
​ 很显然,此时的dp[0][0] = 0;

​ 又因为递推公式是需要比较最大值的,所以所有dp[i][j] = 0;

​ 4.遍历顺序:

​ 经典倒序:

		for (string str : strs) { // 遍历物品
            int oneNum = 0, zeroNum = 0;
            for (char c : str) {
                if (c == '0') zeroNum++;
                else oneNum++;
            }
            for (int i = m; i >= zeroNum; i--) { // 遍历背包容量且从后向前遍历!
                for (int j = n; j >= oneNum; j--) {
                    dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
                }
            }
        }

​ 5.打印dp数组:
在这里插入图片描述

#include<iostream>
#include<string>
#include<vector>
using namespace std;
class solution {
public:
	int findMaxFormvector(vector<string>& strs, int m, int n) {
		vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));//dp数组初始化
		for (vector<string>::size_type i = 0; i < strs.size(); i++) {
			string str = strs[i];
			int zero_nums = 0, one_nums = 0;
			for (string::size_type j = 0; j < str.size(); j++) {
				char c = str[j];
				if (c == '1')	one_nums++;
				else zero_nums++;
			}
			for (int i = m; i >= zero_nums; i--) {
				for (int j = n; j >= one_nums; j--) {
					dp[i][j] = max(dp[i][j], dp[i - zero_nums][j - one_nums] + 1);
				}
			}
			cout << "The current dp array will be shown as below:" << endl;
			for (int i = 0; i <= m; i++) {
				for (int j = 0; j <= n; j++) {
					cout << dp[i][j] << ' ';
				}
				cout << endl;
			}
		}
		return dp[m][n];
	}
};

int main() {
	cout << "Please enter the strings(only 0 and 1 are allowed),seperated by enter,quit with\"stop\"" << endl;
	solution ms;
	vector<string> strs;
	string input;
	while (true) {
		getline(cin, input);
		if (input == "stop")	break;
		strs.push_back(input);
	}
	cout << "Please enter the maximum '0' numbers and '1' numbers:" << endl;
	int m, n;
	cin >> m >> n;
	cout << "The maximum subset's elements is: " << ms.findMaxFormvector(strs, m, n) << endl;
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/611580.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【LLM 论文】Step-Back Prompting:先解决更高层次的问题来提高 LLM 推理能力

论文&#xff1a;Take a Step Back: Evoking Reasoning via Abstraction in Large Language Models ⭐⭐⭐⭐ Google DeepMind, ICLR 2024, arXiv:2310.06117 论文速读 该论文受到的启发是&#xff1a;人类再解决一个包含很多细节的具体问题时&#xff0c;先站在更高的层次上解…

【Git】Github创建远程仓库并与本地互联

创建仓库 点击生成新的仓库 创建成功后会生成一个这样的文件 拉取到本地 首先先确保本地安装了git 可以通过终端使用 git --version来查看是否安装好了git 如果显示了版本信息&#xff0c;说明已经安装好了git&#xff0c;这时候我们就可以进入我们想要clone到问目标文件夹 …

计算机系列之算法分析与设计

21、算法分析与设计 算法是对特定问题求解步骤的一种描述。它是指令的有限序列&#xff0c;其中每一条指令标识一个或多个操作。 它具有有穷性、确定性&#xff08;含义确定、输入输出确定&#xff0c;相同输入相同输出&#xff1b;执行路径唯一&#xff09;、可行性、输入&a…

【SAP ME 38】SAP ME发布WebService配置及应用

更多WebService介绍请参照 【SAP ME 28】SAP ME创建开发组件&#xff08;DC&#xff09;webService 致此一个WebService应用发布成功&#xff0c;把wsdl文件提供到第三方系统调用接口&#xff01; 注意&#xff1a; 在SAP ME官方开发中默认对外开放的接口是WebService接口&am…

01、vue+openlayers6实现自定义测量功能(提供源码)

首先先封装一些openlayers的工具函数&#xff0c;如下所示&#xff1a; import VectorSource from ol/source/Vector; import VectorLayer from ol/layer/Vector; import Style from ol/style/Style; import Fill from ol/style/Fill; import Stroke from ol/style/Stroke; im…

Android GPU渲染SurfaceFlinger合成RenderThread的dequeueBuffer/queueBuffer与fence机制(2)

Android GPU渲染SurfaceFlinger合成RenderThread的dequeueBuffer/queueBuffer与fence机制&#xff08;2&#xff09; 计算fps帧率 用 adb shell dumpsys SurfaceFlinger --list 查询当前的SurfaceView&#xff0c;然后有好多行&#xff0c;再把要查询的行内容完整的传给 ad…

题目----力扣--移除链表元素

题目 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5]示例 2&#xff1a; 输入&…

智慧公厕:让厕所管理变得更智慧、高效、舒适!

公共厕所是城市的重要组成部分&#xff0c;但常常被忽视。它们的管理和养护往往面临着许多问题&#xff0c;例如卫生状况不佳、环境畏畏缩缩、设施老旧等。为了解决这些问题&#xff0c;智慧公厕应运而生。智慧公厕是一种全方位的应用解决方案&#xff0c;将科技与公共厕所管理…

我在洛杉矶采访到了亚马逊云全球首席信息官CISO(L11)!

在本次洛杉矶举办的亚马逊云Re:Inforce全球安全大会中&#xff0c;小李哥作为亚马逊大中华区开发者社区和自媒体代表&#xff0c;跟着亚马逊云安全产品团队采访了亚马逊云首席信息安全官(CISO)CJ Moses、亚马逊副总裁Eric Brandwine和亚马逊云首席高级安全工程师Becky Weiss。 …

搜索的未来:OpenAI 的 GPT 如何彻底改变行业

搜索的未来&#xff1a;OpenAI 的 GPT 如何彻底改变行业 概述 搜索引擎格局正处于一场革命的风口浪尖&#xff0c;而 OpenAI 的 GPT 处于这场变革的最前沿。最近出现了一种被称为“im-good-gpt-2-chatbot”的神秘聊天机器人&#xff0c;以及基于 ChatGPT 的搜索引擎的传言&am…

【C++ 内存管理】深拷贝和浅拷贝你了解吗?

文章目录 1.深拷贝2.浅拷贝3.深拷贝和浅拷贝 1.深拷贝 &#x1f34e; 深拷⻉: 是对对象的完全独⽴复制&#xff0c;包括对象内部动态分配的资源。在深拷⻉中&#xff0c;不仅复制对象的值&#xff0c;还会复制对象所指向的堆上的数据。 特点&#xff1a; &#x1f427;① 复制对…

DCDC中MOS半桥的自举电容,自举电阻问题

一个免费的翻译英文文章的网站&#xff0c;可以将英文数据手册翻译为中文&#xff08;需要挂梯子&#xff0c;不收费&#xff0c;无广告&#xff0c;不需要注册&#xff09;&#xff0c;链接如下&#xff1a; Google 翻译 翻译效果&#xff1a; // 104电容是0.1uf&#xff1b…

Spring AOP(2)

目录 Spring AOP详解 PointCut 切面优先级Order 切点表达式 execution表达式 切点表达式示例 annotation 自定义注解MyAspect 切面类 添加自定义注解 Spring AOP详解 PointCut 上面代码存在一个问题, 就是对于excution(* com.example.demo.controller.*.*(..))的大量重…

Tomcat中服务启动失败,如何查看启动失败日志?

1. 查看 localhost.log 这个日志文件通常包含有关特定 web 应用的详细错误信息。运行以下命令查看 localhost.log 中的错误&#xff1a; sudo tail -n 100 /opt/tomcat/latest/logs/localhost.YYYY-MM-DD.log请替换 YYYY-MM-DD 为当前日期&#xff0c;或选择最近的日志文件日…

【notepad++】使用

1 notepad 下载路径 https://notepad-plus.en.softonic.com/download 2 设置护眼模式 . 设置——语言格式设置——前景色——黑色 . 背景色——RGB &#xff1a;199 237 204 . 勾选“使用全局背景色”、“使用全局前景色” . 保存并关闭

YOLOv5改进 | 注意力机制 | 理解全局和局部信息的SE注意力机制

在深度学习目标检测领域&#xff0c;YOLOv5成为了备受关注的模型之一。本文给大家带来的是能够理解全局和局部信息的SE注意力机制。文章在介绍主要的原理后&#xff0c;将手把手教学如何进行模块的代码添加和修改&#xff0c;并将修改后的完整代码放在文章的最后&#xff0c;方…

RAG查询改写方法概述

在RAG系统中&#xff0c;用户的查询是丰富多样的&#xff0c;可能存在措辞不准确和缺乏语义信息的问题。这导致使用原始的查询可能无法有效检索到目标文档。 因此&#xff0c;将用户查询的语义空间与文档的语义空间对齐至关重要&#xff0c;目前主要有查询改写和嵌入转换两种方…

代码随想录算法训练营第六十天| LeetCode647. 回文子串 、516.最长回文子序列

一、LeetCode647. 回文子串 题目链接/文章讲解/视频讲解&#xff1a;https://programmercarl.com/0647.%E5%9B%9E%E6%96%87%E5%AD%90%E4%B8%B2.html 状态&#xff1a;已解决 1.思路 这道题我只想出来了暴力解法&#xff0c;动规解法并没有想出来。根据视频讲解才把它想出来。…

【hackmyvm】 Animetronic靶机

靶机测试 arp-scanporturl枚举exiftool套中套passwordsudo 提权 arp-scan arp-scan 检测局域网中活动的主机 192.168.9.203 靶机IP地址port 通过nmap扫描&#xff0c;获取目标主机的端口信息 ┌──(root㉿kali)-[/usr/share/seclists] └─# nmap -sT -sV -O 192.16…

基于springboot+vue+Mysql的体质测试数据分析及可视化设计

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…