您的位置:首页 > 其它

poj1328解题报告(贪心、线段交集)

2015-04-29 14:15 369 查看
 
POJ 1328,题目链接http://poj.org/problem?id=1328

题意:

有一海岸线(x轴),一半是陆地(y<0)、一半是海(y>0),海上有一些小岛(用坐标点表示P1、P2...),现要在海岸线上建雷达(覆盖半径R)。给出所有小岛的位置,和雷达半径,求最少需要多少个雷达?
 

思路:

1. 知道小岛位置,和雷达半径,那么以小岛为圆心,雷达覆盖半径为半径画圆,可以求出小岛与x轴有0(雷达无法覆盖)、1(雷达只能在这个点上才能覆盖)、2个交点(雷达在两点之间都能覆盖该小岛)
2. 要求最少雷达多少个,即把雷达放在1中线段的交集内。
那么这就变成了线段交集问题。(贪心)

代码:

//404k 79ms
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>

typedef struct tagLINE{
double left;
double right;
}Line;
void sortLineBuf(Line *p, int num)
{
Line temp;
for (int i=0; i<num; ++i)
{
for (int j=i+1; j<num; ++j)
{
if (p[j].left < p[i].left){
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
}
int main()
{
int caseNum = 0;
double tempPoint;
Line tempLine;
while (true)
{
int islandNum = 0, r = 0;
scanf("%d%d", &islandNum, &r);
if (islandNum == 0 && r == 0) break;

double *p = (double*)malloc(sizeof(double) * islandNum * 2);
double *pX = p;
double *pY = p+islandNum;
for(int i=0; i<islandNum; ++i){
scanf("%lf%lf", &pX[i], &pY[i]);
}
//
int rapar = 0;
bool bImpossible = true;
Line* pLine = (Line*)malloc(sizeof(Line) * islandNum);
//1 转换为直线
for(int i=0; i<islandNum; ++i){
if (fabs(pY[i]) > r){
bImpossible = false;
rapar = -1;
break;
}
tempPoint = sqrt(r*r - pY[i]*pY[i]);
pLine[i].left = pX[i]-tempPoint;
pLine[i].right = pX[i]+tempPoint;
}
if (bImpossible)
{
rapar = 1;
//2
sortLineBuf(pLine, islandNum);
//3 求解线段交集
tempLine = pLine[0];
for (int i=1; i<islandNum; ++i)
{
if (pLine[i].left > tempLine.right)
{
++rapar;
tempLine = pLine[i];
}
else if (pLine[i].right < tempLine.right)
{
tempLine = pLine[i];
}
}
}
printf("Case %d: %d\n", ++caseNum, rapar);
free(p);
free(pLine);
}

return 0;
}


 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: