POJ1328
/*
****************************************************************
算法原理:
1)以海岛(x,y)为圆心,覆盖范围dist为半径画圆,则与x轴存在
①0个交点:y>dist的情况,case输出为-1;
②2个交点:得到x轴范围区间(left,right);
由三角形勾股定理得:left= x-sqrt(dist*dist - y*y);
right=x+sqrt(dist*dist - y*y);
③1个交点:left=right情况,不另做处理;
2)如果岛1(left1,right1)与岛2(left2,right2)
有交集(经过排序):表明岛1与岛2可以共用一个radar;
否则:radar+1;
3)我们把岛1看成不断吞并岛2(即以left的大小排序后的next)区间的
怪兽,岛1的right与岛2的left比较:
if (岛1的right < 岛2的left) ; radar++; 岛1的right=岛2的right;
if (岛1的right < 岛2的right) ; 岛1的right=岛2的right;
****************************************************************
实现:
1)初始化island结构体,用于记录岛屿坐标
x_cord结构体,即为x轴区间(left,right)
2)while外循环,只有当输入0,0时才退出。
动态分配内存,for内循环保存海岛坐标位置
3)计算区间,使用lambda表达式以left的值sort(n个区间)
4)同样用for循环,更新区间
Notice:最后偷懒没有按题目要求的输出格式输出 :D
****************************************************************
*/
#include<iostream>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
struct island //记录一个case的岛屿情况
{
int x;
int y;
};
struct x_cord //记录一个case的区间情况
{
double left;
double right;
};
vector<x_cord> x_pos;
int main()
{
int count = 0, radar = 0;
while (1)
{
int n, dist;
radar = 1, count++; //radar每次需要重新计数,count则是累加的
cin >> n >> dist;
if (!(n&&dist)) //n!=0&&dist!=0
break;
island* pos = new island[n];
for (int i = 0; i < n; i++)
{
cin >> pos[i].x >> pos[i].y;
if (dist < pos[i].y)
{
cout << "Case " << count << ": " << -1 << endl;
return 0;
}
x_cord temp;
double d = sqrt(dist*dist - pos[i].y*pos[i].y);
temp.right = pos[i].x + d;
temp.left = pos[i].x - d;
x_pos.push_back(temp);
}
sort(x_pos.begin(), x_pos.end(),
[](x_cord m,x_cord n) {return m.left<n.left; }); //lambda表达式对左区间排序
double rightside = x_pos.at(0).right;
for (int i = 1; i < n; i++)
{
if (x_pos.at(i).left>rightside)
{
radar++;
rightside = x_pos.at(i).right;
}
if (x_pos.at(i).right>rightside) // 如果是next.right<current.left,就不更新区间
{
rightside = x_pos.at(i).right;
}
}
cout << "Case " << count << ": " << radar << endl;
}
}