poj1328

解题思路:

   逆向思维:将雷达所能覆盖的区域转换为岛屿能被覆盖是时,对应x轴雷达可处的线段。既以岛屿为 
   圆心,雷达可勘测距离为半径,求x轴相交的线段。
   (1)首先我们求出在每个岛屿放雷达以后在x轴上所能覆盖的区间,是在x轴的上的一个线段,即在这 
   一段上放置雷达可以覆盖到该岛。 
   (2)我们把每个岛对应的线段找出来,只要在这些线段上放置一些雷达,使得所有的线段上都有雷达 
   即可符合题意(注意如果半径为0或者坐标的y轴小于半径的话将无法完成覆盖,输出-1)。 
   (3)我们将线段根据左端点排序,找出如果一个线段包含另一个线段,则可以忽略外面的那一个线段 
  (道理很简单),将其设为无效。 
   (4)在剩下的线段中从左往右遍历,对于每个线段,尽量选取该线段的最右边的点作为雷达,如果之 
    前有雷达在该线段上,则跳过该线段。 
   (5)每次加一个雷达将计数器加一,最后可以得到解。

代码:

    #include<iostream>
    #include<stdio.h>
    #include<math.h>
    #include<string.h>
   #include<algorithm>
    using namespace std;
   //采用逆向思维,贪心策略

  //某个岛屿可被雷达探测到的对应雷达所处的位于x轴的区域
   typedef struct point
   {
      double left;
     double right;
  }point;

   point  arr[1000];
   bool cmp( point&a, point&b)
   {
     return a.left < b.left;//贪心,通过岛屿的位置确定雷达所处的范围
   }

    int main()
   {
int d, n;//d:雷达可探测举例,n:岛屿个数
int kase = 0;
while (cin >> n >> d)
{
	if (n == 0 && d == 0)
		break;
	bool flag = false;//判断是否为无法覆盖的点
	double x, y;//岛屿的坐标
	for (int i = 0; i < n; i++)
	{
		cin >> x >> y;
		//判断岛屿是否无法被覆盖
		if (y > d)
		{
			flag = true;//true标记无法覆盖的点
		}
		//求此时岛屿对应的x轴雷达安置范围
		arr[i].left = x - sqrt(d * d - y * y);
		arr[i].right = x + sqrt(d * d - y * y);
	}
	if (flag ==true)//存在无法覆盖的点
	{
		cout << "Case " << ++kase << ": -1" << endl;
		continue;
	}
	sort(arr, arr + n, cmp);//将arr数组按照cmp方式进行排序
	double right = arr[0].right;
	int ans = 1;//统计雷达数目
	for (int i = 1;i < n; i++)
	{
		if (arr[i].left <=right)
			right = min(right, arr[i].right);//更新
		else
		{
			right = arr[i].right;
			ans++;
		}
	}
	cout << "Case " << ++kase << ": " << ans << endl;
}

  }
posted @ 2020-11-17 15:22  Quella'  阅读(96)  评论(0)    收藏  举报
Live2D