例题一 奶牛晒衣服: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 hi−A∗t<=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=x−sqrt(d2−y2),r=x+sqrt(d2−y2)
考虑-1的情况,当d<y时,
该建筑物不可能被覆盖,即输出-1
进过将所有点进行转换左右操作后,
题目转换成了:
给定n个区间,在数轴上尽可能放的点少,
使得每一个区间都能被覆盖。
那我们可以得出贪心策略:
先将每一个区间按右端点作升序排序
再依次考虑每一个区间操作
- 当前区间没有雷达覆盖时,我们将雷达设在该区间最右端
- 当前区间有雷达覆盖是,直接跳过
#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;
}