您的位置:首页 > 其它

【poj】1328 Radar Installation 快排+贪婪

2015-07-31 21:04 260 查看
先说下我刚开始错误的想法:本想用与一般人不一样的方法,即按岛屿的y坐标递减排列(y相等就按X递增排列),然后每次都先找到y最大的岛屿,并将雷达的x坐标和该岛屿的x坐标一样,

这样雷达就可以侦测更大范围,从island[0]开始枚举找这个属于最大范围的岛屿并把x,y都标记为-1.依次找到把所有的岛屿x,y都标记为-1后输出雷达数.

看似没问题的想法,提交就WA.而且是过了别人给的N组数据.

没办法,自己生成随机数和正确程序对拍,发现死在了一组数据中.觉得这个方法确实有问题.想到了LRJ上面的一个区间选点问题,类似的贪心算法。

正解思路:

相对原点而言,我们假定x负半周方向为“左”,x正半轴方向为“右”。

我们找一个岛屿能被侦测到的极限范围,在雷达侦测区(圆)的左半圆上或者在雷达侦测区(圆)的右半圆上,换句话说当岛屿到雷达的距离等于d时,

雷达可以位于岛屿的左侧也可以位于雷达的右侧。而这就可以分别确定雷达相对与岛屿x的最左坐标和x最右坐标。

最左为:x - sqrt(d*d-y*y); 最右为:x - sqrt(d*d-y*y);

每个岛屿都有这样的最左和最右可被侦测坐标。

根据贪婪的思想,每次都应该将最右可被侦测坐标作为衡量标准。

假定当前的岛屿为cur,当前的下一个为next。

1.如果next的最左可被侦测坐标比cur的最右都大的话,只能再设一个雷达来侦测next了。

2.如果next的最左可被侦测坐标比cur的最右小,这时会有两种情况。

A.next最右 < cur最右

B.next最右 >= cur最右

对于B情况,我们可以直接侦测到next了, 可以找next的next了.

对于A情况,也就等价于next包含于cur, 这样就应该把next的右最为衡量标准了.

因为这样可以左移最右坐标, 可以让可能更多的岛屿被侦测到(他们的最左与衡量标准有更多的交集)

具体实现看代码

点击(此处)折叠或打开

#include <math.h>

#include <stdio.h>

#include <stdlib.h>

#define MAX 1001

typedef struct

{

double xl;
//最左可被侦测坐标

double xr;
//最右可被侦测坐标

}coordinate;

coordinate island[MAX]={0};

//按xl递减排序

int cmp(const void* a,
const void *b)

{

return ((coordinate
*)a)->xl
> ((coordinate
*)b)->xl
? 1 :
-1;

}

/******************************************************

|func: 贪婪算法找最少雷达数

|args: 岛屿可被侦测坐标island,岛屿数n,雷达侦测半径d

|retn: 可侦测所有岛屿的最少雷达数

******************************************************/

int Greedy(coordinate island[],
int n,
int d)

{

int num = 0, i;

double cur;
//当前最右可被侦测坐标

cur = island[0].xr;

num++;

for (i=1; i<n; i++)

{

if (island[i].xl
- cur > 1e-5)
//下个岛屿的最左坐标大于当前最右可被侦测坐标

{

num++;

cur = island[i].xr;

}

else

{

if
(island[i].xr
- cur < 1e-5)
//下个岛屿的最右坐标小于当前最右可被侦测坐标

{

cur = island[i].xr;

}

}

}

return num;

}

int main()

{

int i, n, d, x, y, count
= 0, flag
= 0;

double offset;

while(scanf("%d %d",
&n,
&d) == 2
&&
!(n==d
&& 0==d))

{

flag = 0;

count++;

for (i=0; i<n; i++)

{

scanf("%d %d",
&x,
&y);

if
(y > d)

{

flag = 1;

}

offset = sqrt((double)(d
* d - y
* y));

island[i].xl
= x - offset;

island[i].xr
= x + offset;

}

if (flag)

{

printf("Case %d: -1n", count);

continue;

}

qsort(island, n, sizeof(island[0]),
cmp);

i = Greedy(island, n, d);

printf("Case %d: %dn", count, i);

}

return 0;

}

Problem: 1328 User: angrad

Memory: 156K Time: 0MS

Language: C Result: Accepted

转载地址:http://blog.chinaunix.net/uid-22609852-id-3506134.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: