Problem Description
我们假设海岸线是一条无限直线:以海岸线为界,陆地和海洋被分开,在海边分布着很多小岛。现在,我们在海岸线上安装雷达,每个雷达有固定的通讯范围(以d为半径的圆形区域),这样,海边的小岛就可以被某个雷达信号覆盖。
这里我们使用笛卡尔坐标系,定义海岸线为x轴,x轴上方是海洋,下方是陆地。给出分布在海边每个小岛的坐标位置和雷达信号能覆盖的范围d,你的任务是计算出最小需要安装的雷达数目,使得这些雷达信号能覆盖到所有海边的小岛。每个小岛的坐标格式为(x,y)。
如下图所示,给出第一个输入样例的坐标表示,这样在(-2,0),(1,0)上分别安装雷达就可以覆盖所有的小岛(p点),所以我们只需要安装2个雷达。Input
输入包含多组测试样例。每组测试第一行包含两个整数n(1<=n<=1000)和d,n表示小岛的数目,d表示雷达能覆盖的范围的半径。接下来n行,每行由整数x和y组成,表示n个小岛的坐标位置。每两组数据之间有一个空行。
输入0 0表示输入的结束。Output
对于每一组输入,按照输出样例中的格式输出:包含输出序号和最少需要安装雷达的数目。如果找不到解决方案,即不能找到一种安装方案覆盖所有的小岛,输出”-1”。
Sample Input
3 2 1 2 -3 1 2 1 1 2 0 2 0 0Sample Output
Case 1: 2 Case 2: 1
解题思路:(贪心算法)
①为岛屿坐标定义一个结构体,包含横坐标x和纵坐标y
②定义一个容器v装所有的岛屿
③对容器v,将所有岛屿按横坐标从小到大排序
④定义一个目标数组aim,装所有雷达横坐标。目标数组aim初始为空,接下来将从左到右找到每一个雷达。
④开始遍历每一个岛屿
⑤如果岛屿纵坐标大于雷达半径d,则不在雷达范围,输出-1
⑥先根据第一个岛屿找到第一个雷达,若岛屿横纵坐标分别为x和y,则雷达横坐标x0=x+根号(d^2-y^2)。这样找到的是最佳雷达位置,把第一个雷达横坐标加入目标数组aim。
⑦接下来的所有岛屿,都判断其是否在最新雷达的范围内,判断公式为(x-x0)^2+y^2<=d^2。如果在,则不做任何操作,去找下一个岛屿;如果不在,则根据当前岛屿找新的雷达,找新雷达横坐标的方法与⑥相同。
⑧输出目标数组aim的长度,就是雷达的最小个数啦~
代码(注释超详细哦):
#include <iostream>
#include <vector>
#include<math.h>
#include<sstream>
#include <algorithm> //find函数在此头文件
using namespace std; //使用vector就要加这一行
//为岛屿坐标定义一个结构体
struct spot
{
int x,y;
};
//用于岛屿排序,按岛屿横坐标从小到大排序
bool vv(const spot &a,const spot &b)
{
return a.x < b.x;
}
int main()
{
int n,d;
int count=0; //记录这是第几组测试
while(cin>>n>>d){
if(n==0&&d==0) break;
vector<spot> v(n); //定义一个动态数组v,里面每个元素是一个岛屿
for(int i=0;i<n;i++){
cin>>v[i].x>>v[i].y;
}
vector<int> aim; //定义目标数组,装有所有雷达横坐标,且里面雷达横坐标是从小到大排序的
sort(v.begin(),v.end(),vv); //按岛屿横坐标将岛屿从小到大排序
for(int i=0;i<n;i++){ //遍历每一个岛屿
if(v[i].y>d){ //如果岛屿纵坐标大于雷达半径,则肯定不在雷达范围,输出-1
cout<<-1<<endl;
break;
}
if(i==0){ //根据第一个岛屿找第一个雷达位置
int x0; //新雷达的横坐标
if(v[i].x<0){ //当岛屿横坐标为负数,则令雷达坐标向上取整,如-2.3则取-3
x0 = v[i].x+sqrt(d*d-v[i].y*v[i].y)-1;
aim.push_back(x0); //将雷达横坐标加入目标数组
}else{ //当岛屿横坐标为正数,则令雷达横坐标向下取整,如2.3则取2
x0 = v[i].x+sqrt(d*d-v[i].y*v[i].y);
aim.push_back(x0);
}
}else{
if((v[i].x-aim.back())*(v[i].x-aim.back())+v[i].y*v[i].y>d*d){ //如果目标数组中最后一个雷达与当前岛屿的距离大于雷达半径(说明该岛屿不在最后一个雷达范围中),则寻找下一个雷达
int x0;
if(v[i].x<0){
x0 = v[i].x+sqrt(d*d-v[i].y*v[i].y)-1;
aim.push_back(x0);
}else{
x0 = v[i].x+sqrt(d*d-v[i].y*v[i].y);
aim.push_back(x0);
}
}
}
}
count++;
string b = "Case ";
string a = ": ";
stringstream ss;
ss<<b<<count<<a<<aim.size(); //拼接字符串与数字,按要求输出
cout<<ss.str()<<endl;
}
}