使用贪心法,以各个岛为圆心,雷达范围为半径作圆,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;
}