雷达安装(区间贪心)
题目:
Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point locating in the sea side. And any radar installation, locating on the coasting, can only cover d distance, so an island in the sea can be covered by a radius installation, if the distance between them is at most d.
We use Cartesian coordinate system, defining the coasting is the x-axis. The sea side is above x-axis, and the land side below. Given the position of each island in the sea, and given the distance of the coverage of the radar installation, your task is to write a program to find the minimal number of radar installations to cover all the islands. Note that the position of an island is represented by its x-y coordinates.Figure A Sample Input of Radar Installations Input
The input consists of several test cases. The first line of each case contains two integers n (1<=n<=1000) and d, where n is the number of islands in the sea and d is the distance of coverage of the radar installation. This is followed by n lines each containing two integers representing the coordinate of the position of each island. Then a blank line follows to separate the cases.
The input is terminated by a line containing pair of zerosOutput
For each test case output one line consisting of the test case number followed by the minimal number of radar installations needed. "-1" installation means no solution for that case.Sample Input
3 2 1 2 -3 1 2 1 1 2 0 2 0 0Sample Output
Case 1: 2 Case 2: 1
翻译:
描述
假设滑行是一条无限的直线。陆地在滑行的一侧,大海在另一侧。每个小岛都是位于海边的一个点。而任何安装在滑行上的雷达,都只能覆盖d距离,所以海中的一个岛屿可以被一个半径装置覆盖,如果它们之间的距离最多是d.
我们使用笛卡尔坐标系,定义滑行是x轴。海侧在 x 轴上方,陆地侧在下方。给定每个岛屿在海中的位置,并考虑到雷达装置的覆盖范围的距离,您的任务是编写一个程序来找到覆盖所有岛屿的最小数量的雷达装置。请注意,岛屿的位置由其 x-y 坐标表示。
我们使用笛卡尔坐标系,定义滑行是x轴。海侧在 x 轴上方,陆地侧在下方。给定每个岛屿在海中的位置,并考虑到雷达装置的覆盖范围的距离,您的任务是编写一个程序来找到覆盖所有岛屿的最小数量的雷达装置。请注意,岛屿的位置由其 x-y 坐标表示。
输入
输入由多个测试用例组成。每个情况的第一行包含两个整数 n (1<=n<=1000) 和 d,其中 n 是海洋中的岛屿数,d 是雷达装置的覆盖距离。后跟 n 行,每行包含两个整数,表示每个岛屿位置的坐标。然后,下面用一个空行分隔案例。
输入由包含一对零的线终止。
输入由包含一对零的线终止。
输出
对于每个测试用例输出,一行由测试用例编号组成,后跟所需的最小数量的雷达安装。"-1"安装意味着没有针对该情况的解决方案。
分析:
1. 对于范围为d的雷达,可以换一种思维,每个岛屿都有范围为d的辐射,如果与陆地有交点,则表示陆地上存在雷达能射到它;如果不存在交点,则表示不可能存在雷达能射到它
2. 通过1的思想可以得到每个岛屿可以接收的雷达的范围,将范围进行排序,优先left升序,left相同则right升序
3. 对各个区间融合,用current记录当前交集的右端,因为left一直是升序,所以无需记录left。当前结点的left>current,则number++,并且重置current=right(因为left升序,所以上一个交集区间不可能再会有新 岛屿了);如果left<=current,直接更小current即可(current取current和当前节点右端点的小值)
解答:
/* ------------------------------------------------- Author: wry date: 2022/3/4 11:10 Description: test ------------------------------------------------- */ #include <iostream> #include <algorithm> #include <cmath> using namespace std; const int MAXN = 1000+10; struct Region{ double left; double right; }; bool compare(Region &a,Region &b) { if (a.left==b.left) { return a.right<b.right; } return a.left<b.left; //优先起点升序,起点相同看终点 } Region region[MAXN]; int main() { int n,d,CaseNumber=1,x,y; while (cin >> n >> d) { if (n==0 && d==0) { break; } bool isOK = true; for (int i=0;i<n;i++) { cin >> x >> y; if (y>d || !isOK) { //不能直接在这里break,因为还没有输入完,continue就行了 isOK= false; continue; } double k = sqrt(d*d-y*y*1.0); //pow(x,y)==x^y;sqrt(double x)=x开方 region[i].left = x - k; region[i].right = x + k; } if (!isOK) { // 如果构造不成直接输出 cout << "Case " << CaseNumber << ": -1" << endl; CaseNumber++; } else { sort(region,region+n, compare); int number = 1; double current = region[0].right; for (int i=1;i<n;i++) { if (region[i].left<=current) { //因为以left排序的,left一定为升序,所以只要拿current记录right即可 current = min(current,region[i].right); } else if (region[i].left>current) { number++; current = region[i].right; } } cout << "Case " << CaseNumber << ": " << number << endl; CaseNumber++; } } return 0; }