现在的位置: 首页 > 综合 > 正文

poj1328

2013年11月16日 ⁄ 综合 ⁄ 共 978字 ⁄ 字号 评论关闭

贪心。

一开始的思路:

图中ABCD为海岛的位置。假设本题半径为2(符合坐标系),那么A点坐标为(1,1)以此类推。

在题中,记录每个点的坐标,并把一个点新加一个标记变量以标记是否被访问过。

首先以A为圆心,r为半径做圆,交x轴与E1(右)点,做出如图中绿色虚线圆。然后以E1为圆心,半径为r做圆。看此时下一点(B)是否在该圆中。如果在,那么将该点标记变量变为true,再判下一点(C),如果不在那么就新增一个雷达。

后来,换了思路,存储图中红色圆与X轴的交点。

还是原来的贪心思路,仍然先排序,但排序的准则是按红色圆与x轴左交点的先后顺序。

如图,如果B点圆(且如此称呼)的左交点(J1点)在A点圆右交点(E1)左侧,那么B点一定涵盖在A点圆内部。再如图,如果D点圆的左交点(图中未标示)在A点圆的右交点(未标示)右,则D点不在A点圆中。

故,有如下代码:

#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <math.h>

using namespace std;

struct point
{
	double left, right;
}p[2010], temp;

bool operator < (point a, point b)
{
	return a.left < b.left;
}

int main()
{
	int n;
	double r;
	int kase = 0;
	while (cin >> n >> r && (n || r))
	{
		bool flag = false;
		for (int i = 0; i < n; i++)
		{
			double a, b;
			cin >> a >> b;
			if (fabs(b) > r)
			{
				flag = true;
			}
			else
			{
				p[i].left = a * 1.0 - sqrt(r * r - b * b);
				p[i].right = a * 1.0 + sqrt(r * r - b * b);
			}
		}
		cout << "Case " << ++kase << ": ";
		if (flag)
		{
			cout << -1 << endl;
		}
		else
		{
			int countt = 1;
			sort(p, p + n);
			temp = p[0];
			
			for (int i = 1; i < n; i++)
			{
				if (p[i].left > temp.right)
				{
					countt++;
					temp = p[i];
				}
				else if (p[i].right < temp.right)
				{
					temp = p[i];
				}
			}
			cout << countt << endl;
		}
	}
}





抱歉!评论已关闭.