高速公路【贪心·区间选点】
题目描述
一天,唐僧得到了一个消息,在遥远的西天有许多宝藏,他决定去寻找宝藏。
在通往目的地的路途上要通过一片人迹罕至的空地,空地中央只有一些零星的村庄。为了节约时间,他决定在出发前让他的三个徒弟在这片空地边缘(即x轴)修一条笔直的高速路。 因为路途遥远,而且他们并不会瞬移,所以他们不得不经常下道,寻找一个村庄进行补给。
唐僧的三个徒弟叫苦不迭,不想修太多的下道口。因此,他们决定聘请智慧的你,在高速路上设计出最少的出口,使得每个村庄到离他最近的一个出口的距离不超过D。
注意:本题的距离指欧几里德距离,且距离值为浮点数。输入格式
多组数据,对于每组数据:
第一行是高速路的长度 L(高速路从坐标原点开始);
第二行是最大距离 D;
第三行是村庄的个数 N;
接下来的 N 行,每行有两个整数 X,Y,表示这一个村庄的坐标.
输入数据保证有解。输出格式
对于每组数据:
一行,最少的出口个数。- 样例输入
100
50
3
2 4
50 10
70 30
- 样例输出
1
思路解析
如图,我们可以求出出口应在的区间内。
然后,是不是觉得这道题特别熟悉呢?这道题就转化为了贪心算法中的区间选点问题。
这里简单描述一下,以右端点从左到右排序,然后每次选点选在区间的右端点,如果两个区间有重叠部分就可以共用一个出口。
程序实现
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN 1000
struct node{
int x,y;
double l,r;
}a[MAXN+5];
int L,D,N;
bool cmp(node p,node q)
{
return p.r<q.r;
}
int main()
{
while(scanf("%d %d %d",&L,&D,&N)!=EOF)
{
for(int i=1;i<=N;i++)
{
scanf("%d %d",&a[i].x,&a[i].y);
double temp=sqrt(D*D-a[i].y*a[i].y);
a[i].l=a[i].x-temp>=0?a[i].x-temp:0;
a[i].r=a[i].x+temp<=L?a[i].x+temp:L;//计算区间左右端点,用勾股定理
}
sort(a+1,a+N+1,cmp);//按右端点排序
double x=-1;
int ans=0;
for(int i=1;i<=N;i++)//贪心
if(a[i].l<=x) continue;
else
{
ans++;
x=a[i].r;
}
printf("%d\n",ans);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现