ACwing 112. 雷达设备 贪心 一刀切线段问题

假设海岸是一条无限长的直线,陆地位于海岸的一侧,海洋位于另外一侧。

每个小岛都位于海洋一侧的某个点上。

雷达装置均位于海岸线上,且雷达的监测范围为d,当小岛与某雷达的距离不超过d时,该小岛可以被雷达覆盖。

我们使用笛卡尔坐标系,定义海岸线为x轴,海的一侧在x轴上方,陆地一侧在x轴下方。

现在给出每个小岛的具体坐标以及雷达的检测范围,请你求出能够使所有小岛都被雷达覆盖所需的最小雷达数目。
输入格式

第一行输入两个整数n和d,分别代表小岛数目和雷达检测范围。

接下来n行,每行输入两个整数,分别代表小岛的x,y轴坐标。

同一行数据之间用空格隔开。
输出格式

输出一个整数,代表所需的最小雷达数目,若没有解决方案则所需数目输出“-1”。
数据范围

1≤n≤1000

输入样例:

3 2
1 2
-3 1
2 1

输出样例:

2

题意 :
第一象限有n个点,要在x轴上建一些雷达(给定雷达半径R),要求所有的点都可以被监听到
问最少要装多少个雷达 ?
如图

逆向考虑,以黑点为圆心画半径为R的圆,如图
于是对所有点都画圆,可以得到多个可能重叠的区间
问题就转化成了经典的线段一刀切问题

线段一刀切问题 :
n n n条线段(可能重叠),最少切几刀可以切到所有线段?
如图:

对于每条线段按照结束点排序,结束点相同按起点排序
每次切都直接切这条线段的结束点,如果结束点不被后面的某条线段覆盖到,就说明要多切一刀

代码如下

bool cmp(Node& A, Node& B) {
	return A.rig == B.rig ? A.lef < B.lef : A.rig < B.rig;
}
sort(a+1, a+1+n, cmp);
double lst = -INF;
int ans = 0;
for(int i=1; i<=n; i++) {
	if(a[i].lef > lst) {
		ans ++;
		lst = a[i].rig;
	}
}

完整代码

#define debug
#ifdef debug
#include <time.h>
#include "/home/majiao/mb.h"
#endif

#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <math.h>

#define MAXN ((int)1e5+7)
#define ll long long int
#define fori(lef, rig) for(int i=lef; i<=rig; i++)
#define forj(lef, rig) for(int j=lef; j<=rig; j++)
#define fork(lef, rig) for(int k=lef; k<=rig; k++)
#define QAQ (0)

using namespace std;

#define show(x...) \ do { \ cout << "\033[31;1m " << #x << " -> "; \ err(x); \ } while (0)

void err() { cout << "\033[39;0m" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cout << a << ' '; err(x...); }

namespace FastIO{

	char print_f[105];
	void read() {}
	void print() { putchar('\n'); }

	template <typename T, typename... T2>
		inline void read(T &x, T2 &... oth) {
			x = 0;
			char ch = getchar();
			ll f = 1;
			while (!isdigit(ch)) {
				if (ch == '-') f *= -1; 
				ch = getchar();
			}
			while (isdigit(ch)) {
				x = x * 10 + ch - 48;
				ch = getchar();
			}
			x *= f;
			read(oth...);
		}
	template <typename T, typename... T2>
		inline void print(T x, T2... oth) {
			ll p3=-1;
			if(x<0) putchar('-'), x=-x;
			do{
				print_f[++p3] = x%10 + 48;
			} while(x/=10);
			while(p3>=0) putchar(print_f[p3--]);
			putchar(' ');
			print(oth...);
		}
} // namespace FastIO
using FastIO::print;
using FastIO::read;

int n, m, Q, K;
double R;

struct Node {
	double lef, rig;
} a[MAXN];

bool cmp(Node& A, Node& B) { //先按终点排序,终点相同按起点排序
	return A.rig == B.rig ? A.lef < B.lef : A.rig < B.rig;
}

#define eps (1e-6)
#define INF (1e10)

int main() {
#ifdef debug
	freopen("test", "r", stdin);
	clock_t stime = clock();
#endif
	scanf("%d %lf ", &n, &R);
	for(int i=1; i<=n; i++) {
		double x, y;
		scanf("%lf %lf ", &x, &y);
		
		if(y > R) { printf("-1\n"); return 0; } //y太高了就无解

		double d = sqrt(R*R - y*y); //勾股定理
		double lef = x - d, rig = x + d;
		a[i] = { lef, rig };
	}
	sort(a+1, a+1+n, cmp);
	double lst = -INF; //初值负无穷
	int ans = 0;
	for(int i=1; i<=n; i++) {
		if(a[i].lef > lst) { //第i条线段无法被上一刀切到
			ans ++;          //多切一刀
			lst = a[i].rig;  //这刀切在这条线段末尾
		}
	}
	printf("%d\n", ans);




#ifdef debug
	clock_t etime = clock();
	printf("rum time: %lf 秒\n",(double) (etime-stime)/CLOCKS_PER_SEC);
#endif 
	return 0;
}




全部评论

相关推荐

2025-12-28 16:32
重庆邮电大学 Java
程序员花海:1.技能放最后,来面试默认你都会,技能没啥用 2.实习写的看起来没啥含金量,多读读部门文档,包装下 接LLM这个没含金量 也不要用重构这种 不会给实习生做的 3.抽奖这个还是Demo项目,实际在公司里面要考虑策略,满减,触发点,触发规则 库存 之类的,不是这个项目这么简单 4.教育背景提前,格式为 教育背景 实习 项目 技能 自我评价
简历被挂麻了,求建议
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务