贪心算法——思路与例题

news2025/4/1 9:27:31

贪心算法:当我们分析一个问题时,我们往往先以最优的方式来解决问题,所以顾名思义为贪心。

例题1

题目分析:这题利用贪心算法来分析,最优解(可容纳人数最多时)一定是先考虑六人桌,然后再考虑四人桌。

1:六人桌

  • 把两个三人寝安排到六人桌(可容纳6人)
  • 其次就是把一个二人寝安排到六人桌,这样子还多出了一个四人桌(可容纳2人,但是多了一张四人桌)
  • 再考虑把一个四人寝安排到六人桌(可容纳四人)
  • 最后是把三人寝安排到六人桌(可容纳三人)

2:四人桌

  • 最优解就是把四人寝安排到四人桌(可容纳四人)
  • 其次是把两个二人寝安排到四人桌(可容纳四人)
  • 把一个三人寝安排到四人桌(可容纳三人)
  • 把一个二人寝安排到四人桌(可容纳两人)

以上就是最优解的排序过程,我们只要按照这个顺序来安排位置,那么可以容纳的人数一定是最多的。

代码实现:

#include <iostream>
using namespace std;

inline void  solve()
{
	int a2, a3, a4, b4, b6,ct=0;
	cin>>a2>>a3>>a4>>b4>>b6;
	/*先考虑六人桌*/
	while (a3 >= 2 && b6)/*有两个三人寝,且有六人桌时*/
	{
		ct += 6; a3 -= 2; b6 --;
	}
	while (a2 && b6)/*有一个二人寝,且有六人桌时*/
	{
		ct += 2; a2--; b6--; b4++;
	}
	while (a4 && b6)/*有一个四人寝,且有六人桌时*/
	{
		ct += 4; a4--; b6--;
	}
	while (a3 && b6)/*有一个三人寝,且有六人桌时*/
	{
		ct += 3; a3--; b6--;
	}
	/*再考虑四人桌*/
	while (a4 && b4)/*当有四人寝,且有四人桌时*/
	{
		ct += 4; a4--; b4--;
	}
	while (a2 >= 2 && b4)/*当有两个二人寝,且有四人桌时*/
	{
		ct += 4; a2 -= 2; b4--;
	}
	while (a3 && b4)/*当有三人寝,且有四人桌时*/
	{
		ct += 3; a3--; b4--;
	}
	while (a2 && b4)/*当有二人人寝,且有四人桌时*/
	{
		ct += 2; a2--; b4--;
	}
	cout << ct << endl;
}
int main()
{
	int n;
	cin >>n;
	while (n--)
	{
		solve();
	}
	return 0;
}

例题2(巧克力)

题目分析:现在一共有n种巧克力,每种巧克力包含三个信息:价格,保质期,数量。现在要买能吃x天的巧克力(一天吃一块),题目要求花的钱最少。现在思考有没有一种最优路径可以达到我们的目的如果有,那么就可以使用贪心算法。

再进一步分析,在保质期没过的前提下,我们能选择的巧克力种类越多越好,这样我们就可以在这些种类里选择价格最低的。那么我们应该倒序考虑,这样我们可以选择的巧克力种类才最多,因为在第x天时,我们选择的巧克力的保质期一定是大于等于x的,这就意味着,当在1—x天里的任意一天时,可以选择的巧克力种类最多。

代码实现:

#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int x, n;
const int N = 1e5 + 5;

struct Q 
{
	int id, value;
	bool operator< (const Q& rhs) const { return value > rhs.value; }/*重载为小到大*/
};
priority_queue <Q> q;/*大堆根.价格*/
struct Node 
{
	int price, date, amount;
	bool operator<(const Node& rhs)const { return date > rhs.date; }/*重载<为降序*/

}cho[N];
int main()
{
	ios::sync_with_stdio(false);
	int sum = 0,st=1;
	cin >> x >> n;
	for (int i = 1; i <= n; i++)
	{
		cin>>cho[i].price>> cho[i].date >> cho[i].amount;
	}
	sort(cho + 1,cho+1+n);/*按照保质期从大到小排序*/
	int pos=1;
	for (int i = x; i >= 1; i--)/*当在第i天时*/
	{
		
		while (pos <= n && cho[pos].date >= i)/*把满足条件的巧克力种类都列入考虑范围*/
		{
			cho[pos].amount--;
			q.push({ pos, cho[pos].price });/*队列中最多有n组数据,且按照价格升序*/
			pos++;
		}
		if (q.empty())
		{
			st = 0;
				break;
		}
		Q now = q.top();/*得到价格最低的巧克力信息*/
		sum += now.value;
		if (cho[now.id].amount)/*如果这种巧克力还有,继续列入考虑范围*/
		{
			cho[now.id].amount--;
			q.push({now.id,cho[now.id].price});
		}
		q.pop();/*选择吃掉价格最低的巧克力*/
		
	}
	if (st == 0)cout << "-1" << endl;
	else cout << sum;
	cout << sum;
	return 0;
}

代码分析:使用优先队列来实现对价格的升序排列。优先队列中只存放巧克力的种类和价格。以方便我们选择价格最低的巧克力,种类是用来找到这种价格最低的巧克力的数量的,所以不可或缺。

我们先按照保质期对巧克力进行降序排序(大的在前,小的在后)。然后在选择出可以吃的巧克力类别(一共有n种类别),当我把某种巧克力列入考虑范围之后(放到优先队列中),这种巧克力的数量要减一。当完成判断后,此时优先队列中就是我们在第i天时总共可以选择的巧克力了,因为我们优先队列我们按照价格升序排列的,所以取出队头(价格最低)信息之后,判断这种巧克力是否还有,有的话再存入到优先队列q之中,还要把对头对应的种类数量减一。最后要弹出队头,表示吃了这块巧克力。如果在遍历的过程中出现了队列为空的情况,说明没有解决方案。

例题3(三国游戏)

题目分析:要想知道当某个国家获胜时最多有多少个事件发生,我们首先思考有没有某种最优路径能判断出某个国家胜利时的发生的最多事件,然后取出这三个国家发生的事件的最大值。这里主要的困难就是获胜条件:a>b+c如何转变,如何达到最简判断出这个国家获胜时最多能发生的事件。

数据转变:把第i个事件三个独立的值转化为一个值,但是这个值包含了这三个独立数据的信息,我们通过判断这个值的大小,就可以知道这个国家有没有获胜。那么如何实现呢,具体就是对于第一个国家,那么这个值就是a-b-c,对于第二个国家,这个值就是b-a-c,对于第三个国家,这个值就是c-a-b,可以看出,其实就是相对值,也就是这个事件发生时,对第一个国家,第二个国家,第三个国家的胜利的贡献值。贡献值越大,说明这个事件发生对某个国家胜利越有利。所以问题就迎刃而解了,我们把复杂的三个数据简化为了一个数据,只需要对这个数据进行降序排序,先发生贡献值大的事件,先加正的,再加负的。循环计算求和,当和小于零时,说明这个国家已经失败了。这样我们就判断出了最多发生的事件数量。然后比较这三个国家的事件数量,取最大值即可。

#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
int x, n;
const int N = 1e5 + 5;

struct abc 
{
	long long int a, b, c,pure_a,pure_b,pure_c;

}ABC_i[N];
bool max_a(const struct abc &s1, const struct abc& s2)
{
	return s1.pure_a >s2.pure_a;
}
bool  max_b(const struct abc& s1, const struct abc& s2)
{
	return s1.pure_b > s2.pure_b;
}
bool  max_c(const struct abc& s1, const struct abc& s2)
{
	return s1.pure_c > s2.pure_c;
}
int  win(int x)
{
	int ct=0,sum=0;
	if (x == 1)
	{
		
		sort(ABC_i+1,ABC_i+1+n, max_a);/*判断X国*/
		for (int i = 1; i <= n; i++)
		{
			if (sum + ABC_i[i].pure_a > 0)
			{
				sum+= ABC_i[i].pure_a;
					ct++;
			}
			else break;
		}
		
	}
	if (x == 2)
	{

		sort(ABC_i + 1, ABC_i + 1 + n, max_b);/*判断Y国*/
		for (int i = 1; i <= n; i++)
		{
			if (sum + ABC_i[i].pure_b > 0)
			{
				sum += ABC_i[i].pure_b;
				ct++;
			}
			else break;
		}

	}
	if (x == 3)
	{

		sort(ABC_i + 1, ABC_i + 1 + n, max_c);/*判断Z国*/
		for (int i = 1; i <= n; i++)
		{
			if (sum + ABC_i[i].pure_c > 0)
			{
				sum += ABC_i[i].pure_c;
				ct++;
			}
			else break;
		}

	}
	if (ct == 0) ct = -1;
	return ct;
}
int main()
{
	int answer=-1,x,y,z;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> ABC_i[i].a;
	}
	for (int i = 1; i <= n; i++)
	{
		cin >> ABC_i[i].b;
	}
	for (int i = 1; i <= n; i++)
	{
		cin >> ABC_i[i].c;
	}
	for (int i = 1; i <= n; i++)
	{
		
		x = ABC_i[i].a - ABC_i[i].b - ABC_i[i].c;
		ABC_i[i].pure_a = x;

		y = ABC_i[i].b - ABC_i[i].a - ABC_i[i].c;
		ABC_i[i].pure_b = y;

		z = ABC_i[i].c - ABC_i[i].b - ABC_i[i].a;
		ABC_i[i].pure_c = z;
	}
	
	/*for (int i = 1; i <= n; i++)
	{
		cout << ABC_i[i].pure_a << " " << ABC_i[i].pure_b << " " << ABC_i[i].pure_c << endl;;
	}*/
	for (int i = 1; i <= 3; i++)
	{
		answer=max(win(i),answer);
	}
	cout << endl<<endl<< " " << answer;
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络华为HCIA+HCIP 防火墙

防火墙部署模式 路由模式 有路由器的功能 路由器干的活 他都得干 透明模式 旁挂模式 IDS 端口镜像 VPN

WordPress超级菜单插件UberMenu v3.78汉化版

一、插件介绍 UberMenu 是一款功能强大的 WordPress 超级菜单插件,能够帮助站长创建响应式、可自定义的多级菜单。该插件支持动态内容加载、图标、图片、搜索框等丰富功能,并且兼容大多数 WordPress 主题。 UberMenu v3.78 经过完整汉化,适用于中文站点用户,让操作更加直观…

SQL中体会多对多

我们可以根据学生与课程多对多关系的数据库模型&#xff0c;给出实际的表数据以及对应的查询结果示例&#xff0c;会用到JOINLEFT JOIN两种连接 1. 学生表&#xff08;students&#xff09; student_idstudent_name1张三2李四3王五 2. 课程表&#xff08;courses&#xff09…

23种设计模式-备忘录(Memento)设计模式

备忘录设计模式 &#x1f6a9;什么是备忘录设计模式&#xff1f;&#x1f6a9;备忘录设计模式的特点&#x1f6a9;备忘录设计模式的结构&#x1f6a9;备忘录设计模式的优缺点&#x1f6a9;备忘录设计模式的Java实现&#x1f6a9;代码总结&#x1f6a9;总结 &#x1f6a9;什么是…

2024年3月全国计算机等级考试真题(二级C语言)

&#x1f600; 第1题 下列叙述中正确的是 A. 矩阵是非线性结构 B. 数组是长度固定的线性表 C. 对线性表只能作插入与删除运算 D. 线性表中各元素的数据类型可以不同 题目解析&#xff1a; A. 矩阵是非线性结构 错误。矩阵通常是二维数组&#xff0c;属…

【MySQL】索引 事务

目录 一、索引 概念 作用 使用场景 使用 查看索引 创建索引 删除索引 背后的数据结构 二、事务 为什么使用事务 事务的概念 使用 开启事务 执行多条 SQL 语句 回滚或提交&#xff1a;rollback/commit; 事务的基本特性 原子性 一致性 持久性 隔离性 脏读 …

【江协科技STM32】软件SPI读写W25Q64芯片(学习笔记)

SPI通信协议及S为5Q64简介&#xff1a;【STM32】SPI通信协议&W25Q64Flash存储器芯片&#xff08;学习笔记&#xff09;-CSDN博客 STM32与W25Q64模块接线&#xff1a; SPI初始化&#xff1a; 片选SS、始终SCK、MOSI都是主机输出引脚&#xff0c;输出引脚配置为推挽输出&…

Git+Fork 入门介绍

git 分区理解 fork安装 从路径下去拿软件时&#xff0c;注意先拉到本地。经验来看&#xff0c;fork直接安装会出不可思议的问题。 fork操作 安装&#xff0c;注意设置好名字&#xff0c;如果之前安装的同学&#xff0c;名字没有写好&#xff0c;重新安装设置好名字。 clone操…

Windows系统安装Node.js和npm教程【成功】

0.引言——Node.js和npm介绍 项目描述Node.js基于Chrome V8引擎的JavaScript运行环境&#xff0c;使JavaScript可用于服务器端开发。采用单线程、非阻塞I/O及事件驱动架构&#xff0c;适用于构建Web服务器、实时应用和命令行工具等npmNode.js的包管理器与大型软件注册表。拥有…

Axure RP9.0 教程:左侧菜单列表导航 ( 点击父级菜单,子菜单自动收缩或展开)【响应式的菜单导航】

文章目录 引言I 实现步骤添加商品管理菜单组推拉效果引言 应用场景:PC端管理后台页面,左侧菜单列表导航。 思路: 用到了动态面板的两个交互效果来实现:隐藏/显示切换、展开/收起元件向下I 实现步骤 添加商品管理菜单组 在左侧画布区域添加一个菜单栏矩形框;再添加一个商…

科技赋能|ZGIS综合管网智能管理平台守护地下城市生命线

地下管网作为城市公共安全的重要组成部分&#xff0c;担负着城市的信息传递、能源输送、排涝减灾等重要任务&#xff0c;是维系城市正常运行、满足群众生产生活需要的重要基础设施&#xff0c;是城市各功能区有机连接和运转的维系&#xff0c;因此&#xff0c;也被称为城市“生…

如何保证LabVIEW软件开发的质量?

LabVIEW作为图形化编程工具&#xff0c;广泛应用于工业测控、自动化测试等领域。其开发模式灵活&#xff0c;但若缺乏规范&#xff0c;易导致代码可读性差、维护困难、性能低下等问题。保证LabVIEW开发质量需从代码规范、模块化设计、测试验证、版本管理、文档完善等多维度入手…

如何快速解决 Postman 报错?

介绍一些 Postman 常见的报错与处理方法&#xff0c;希望能够对大家有所帮助。 Postman 一直转圈打不开的问题 Postman 报错处理指南&#xff1a;常见报错与解决方法

C++ 多线程简要讲解

std::thread是 C11 标准库中用于多线程编程的核心类&#xff0c;提供线程的创建、管理和同步功能。下面我们一一讲解。 一.构造函数 官网的构造函数如下&#xff1a; 1.默认构造函数和线程创建 thread() noexcept; 作用&#xff1a;创建一个 std::thread 对象&#xff0c;但…

如何设计一个处理物联网设备数据流的后端系统。

一、系统架构设计 物联网设备数据流的后端系统通常包括以下几个主要组件: ①设备数据采集层:负责从物联网设备收集数据。 ②数据传输层:负责将设备数据传输到后端系统。 ③数据处理层:实时或批量处理传输到后的数据。 ④存储层:负责存储设备数据。 ⑤API层:提供外部…

深入理解 Spring Boot 应用的生命周期:从启动到关闭的全流程解析

引言 Spring Boot 是当今 Java 开发中最流行的框架之一&#xff0c;它以简化配置和快速开发著称。然而&#xff0c;要真正掌握 Spring Boot&#xff0c;理解其应用的生命周期是至关重要的。本文将深入探讨 Spring Boot 应用的生命周期&#xff0c;从启动到关闭的各个阶段&…

【算法笔记】图论基础(一):建图、存图、树和图的遍历、拓扑排序、最小生成树

目录 何为图论图的概念 图的一些基本概念有向图和无向图带权图连通图和非连通图对于无向图对于有向图 度对于无向图对于有向图一些结论 环自环、重边、简单图、完全图自环重边简单图 稀疏图和稠密图子图、生成子图同构 图的存储直接存边邻接矩阵存边邻接表存边链式前向星存边 图…

SpringMVC 请求与响应处理详解

引言 在 Java Web 开发中&#xff0c;SpringMVC 作为 Spring 框架的重要模块&#xff0c;提供了强大的请求和响应处理机制。本文将深入探讨 SpringMVC 中请求和响应的处理方式&#xff0c;结合实际案例&#xff0c;帮助开发者更好地理解和应用这些功能。 一、SpringMVC 请求处…

【python】requests 爬虫高效获取游戏皮肤图

1. 引言 在当今的数字时代&#xff0c;游戏已经成为许多人生活中不可或缺的一部分。而游戏中的皮肤&#xff0c;作为玩家个性化表达的重要方式&#xff0c;更是受到了广泛的关注和喜爱。然而&#xff0c;对于许多玩家来说&#xff0c;获取游戏皮肤往往需要花费大量的时间和精力…

(UI自动化测试web端)第二篇:元素定位的方法_css定位之ID选择器

看代码里的【find_element_by_css_selector( )】( )里的表达式怎么写&#xff1f; 文章介绍了第一种写法id选择器&#xff0c;其实XPath元素定位要比CSS好用&#xff0c;原因是CSS无法使用下标&#xff08;工作当中也是常用的xpath&#xff09;&#xff0c;但CSS定位速度比XPat…