POJ 1328

使用贪心法,以各个岛为圆心,雷达范围为半径作圆,X轴与各圆相交得弦(相切可看做对弦取极限),在弦上任意一点放置雷达都能覆盖弦对应的岛,即此弦为可行域。对有公共部分的可行域取交集,则此交集内放置一个雷达可覆盖所有上述可行域对应的岛。


算法首先在输入每个岛的坐标时求其可行域的左右坐标并按可行域左端点坐标排序来保证不遗漏。然后进入贪心选择,对于一个还未被雷达覆盖的岛屿,为其增设雷达站,再判断其后的岛是否与此岛可行域有交集,若有则求交集后继续判断,若无则增设雷达站,重复上述步骤。


一开始我的思路是取每个岛对应的可行域中最右边的点,而不是求范围,这个思路的问题是解不一定在最右端。输入判断也需要特别注意,没有判断n>=0、d>0和岛的纵坐标>=0导致一直WA。


附:另一解题报告及更多测试数据


//#define DEBUG

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

#ifdef DEBUG
#include <time.h>
#endif

#define leftIndex 0
#define rightIndex 1

double islands[1000][2];
int islandCount;
int radarRange;

using namespace std;

bool validData()
{
	cin >> islandCount >> radarRange;
	if (islandCount || radarRange)
		return true;
	return false;
}

void clearInput(int count)
{
	int curX, curY;
	for (; count < islandCount; ++count)
		cin >> curX >> curY;
}

int calcResult()
{
	if (islandCount < 0 || radarRange <= 0)
	{
		clearInput(0);
		return -1;
	}

	if (!islandCount)
	{
		clearInput(0);
		return 0;
	}

	int curX, curY;
	cin >> curX >> curY;
	if (curY < 0 || (curY > radarRange))
	{
		clearInput(1);
		return -1;
	}

	islands[0][leftIndex] = curX - sqrt(static_cast<double>(radarRange*radarRange - curY*curY));
	islands[0][rightIndex] = curX + sqrt(static_cast<double>(radarRange*radarRange - curY*curY));

	for (int count = 1; count < islandCount; ++count)
	{
		int pos;
		double curLeftX;

		cin >> curX >> curY;
		if (curY < 0 || (curY > radarRange))
		{
			clearInput(count + 1);
			return -1;
		}

		curLeftX = curX - sqrt(static_cast<double>(radarRange*radarRange - curY*curY));
		
		for (pos = count - 1; pos >= 0 && islands[pos][leftIndex] > curLeftX; --pos)
		{
			islands[pos + 1][leftIndex] = islands[pos][leftIndex];
			islands[pos + 1][rightIndex] = islands[pos][rightIndex];
		}
		islands[pos + 1][leftIndex] = curLeftX;
		islands[pos + 1][rightIndex] = curX + sqrt(static_cast<double>(radarRange*radarRange - curY*curY));
	}

	int radarCount = 0;
	for (int count = 0; count < islandCount; ++count)
	{
		++radarCount;
		double possibleRangeL = islands[count][leftIndex], possibleRangeR = islands[count][rightIndex];
		for (int temp = count + 1; temp < islandCount && possibleRangeR >= islands[temp][leftIndex]; ++temp)
		{
			if (possibleRangeL <= islands[temp][rightIndex])
			{
				count = temp;
				possibleRangeL = possibleRangeL < islands[temp][leftIndex] ? islands[temp][leftIndex] : possibleRangeL;
				possibleRangeR = possibleRangeR > islands[temp][rightIndex] ? islands[temp][rightIndex] : possibleRangeR;
			}
		}
	}
	return radarCount;
}

int main()
{
	int caseCount = 0;
	while (validData())
	{
#ifdef DEBUG
		clock_t start = clock();
#endif

		++caseCount;
		//sortIslandsByX(0, islandCount-1);
		cout << "Case " << caseCount << ": " << calcResult() << endl;

#ifdef DEBUG
		cout << "This case costs " << static_cast<double>(clock() - start) / CLOCKS_PER_SEC << "s." << endl;
#endif
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值