第一部分 基础算法(第二章 贪心算法)例题

这篇博客通过四个例题详细介绍了贪心算法的应用,包括奶牛晒衣服的最少时间问题、雷达装置的最少安装数量、畜栏预设的最少畜栏数以及国王游戏中最小化大臣奖赏的策略。每个例题都提供了思路和解题方法,利用贪心策略优化问题解决。
摘要由CSDN通过智能技术生成

例题一 奶牛晒衣服:link

题目描述
有 n 件衣服,第 i 件衣服的湿度为 h i h_i hi
在自然条件下,每件衣服每分钟都可以自然晒干 A 点湿度。
在烘干机作用下,可以选择一件衣服,用一分钟的时间晒干 B 点湿度。
求出晒干所有衣服的最少时间(湿度为 0 为干)。

输入格式
第一行三个正整数N, A, B 。
接下来 N 行,第 i 行一个正整数,表示第i 件衣服的湿度 h i h_i hi

输出格式
输出一个数,表示晒干所有衣服的最少时间。

样例
样例输入

3 2 1
1
2
3

样例输出

1

数据范围与提示
对于 100% 的数据,有 1<=N,A,B, h i h_i hi<= 5 X 1 0 5 5X10^5 5X105

思路:
注意到答案与最后一件衣服的湿度有关。
在不考虑吹风机的情况,一定是湿度最大的最后
所以我们希望湿度最大时间最快最好。
所以得到一个贪心策略:每次选最湿的衣服用吹风机
直接的想法是,模拟奶牛晒衣过程,
直到全部衣服被晒干。
我们不需要考虑自然晒干的问题,
h i − A ∗ t < = 0 h_i-A*t<=0 hiAt<=0,表示全部晒干。

由于我们只考虑最湿的衣服,
我们可以用一个priority_queue来维护,
时间复杂度为O( n log ⁡ n n \log n nlogn)。

#include <cstdio>
#include <iostream>
#include <queue> 
using namespace std;
priority_queue<int> q;
int n, A, B, a, t, temp;
int main()
{
   
	scanf("%d%d%d", &n, &A, &B);
	for(int i = 1; i <= n; i++) scanf("%d", &a), q.push(a);
	while(q.top() - t * A > 0) t++, temp = q.top(), q.pop(), q.push(temp - B);
	printf("%d\n", t);
	return 0;
}

例题二 雷达装置:link

题目描述
有 n 个建筑物,第 i 个建筑物在笛卡尔坐标系上的坐标为( x i , y i x_i,y_i xi,yi) ,你需要在 x 轴上安装一些雷达,每个雷达的侦察半径均d为 ,要求每个建筑物都至少被一个雷达侦测到,求最少要安装几个雷达。

输入格式
第一行两个正整数 n,d。

接下来 n 行,第 i 行两个整数 。

输出格式
输出一行表示答案,若没有解决方案,则答案为 -1。

样例
样例输入

3 2
1 2
-3 1
2 1

样例输出

2

数据范围与提示
对于100% 的数据,有1<=n<= 1 0 3 10^3 103

思路:
这题本质上是一个区间放最少点覆盖问题。
在这里插入图片描述

如图,我们将一个点( x i , y i x_i,y_i xi,yi)能覆盖到他的最左和最右算出来,
由勾股定理可得: l = x − s q r t ( d 2 − y 2 ) , r = x + s q r t ( d 2 − y 2 ) l=x-sqrt(d^2-y^2),r=x+sqrt(d^2-y^2) l=xsqrt(d2y2),r=x+sqrt(d2y2)
考虑-1的情况,当d<y时,
该建筑物不可能被覆盖,即输出-1

进过将所有点进行转换左右操作后,
题目转换成了:
给定n个区间,在数轴上尽可能放的点少,
使得每一个区间都能被覆盖。
那我们可以得出贪心策略:
先将每一个区间按右端点作升序排序
再依次考虑每一个区间操作

  1. 当前区间没有雷达覆盖时,我们将雷达设在该区间最右端
  2. 当前区间有雷达覆盖是,直接跳过
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 1e3 + 10;
struct node
{
   
	double l, r;	
} p[N];
int n, x, y, d, ans;
double end = -123456789;
bool cmp(node a, node b) {
   return a.r < b.r;}
int main()
{
   
	scanf("%d%d", &n, &d);
	for(int i = 1; i <= n; i++)
	{
   
		scanf("%d%d", &x, &y);
		if(d < y) {
   printf("-1\n"); return 0;}
		p[i].l = x - sqrt(d * d - y * y * 1.0), p[i].r = x + sqrt(d * d - y * y * 1.0);
	}
	sort(p + 1, p + 1 + n, cmp);
	for(int i = 1; i <= n; i++)
		if(p[i].l > end) ans++, end = p[i].r;
	printf("%d", ans);
	return 0;
} 

例题三 畜栏预设:link

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值