【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
这样雷达就可以侦测更大范围,从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
相关文章推荐
- win7下,本机Apache虚拟主机配置
- Android开发——下载功能的逻辑和实现
- DRP学习之路--Filter生命周期
- 过河问题
- TCP 传输 滑动窗口
- LeetCode之Merge k Sorted Lists
- 单链表的建立/测长/打印
- 2015年多校联合训练第四场(Problem Killer)hdu5328
- IIS配置支持apk文件下载
- UVALive 6661
- poj 3365 数学分类(最大的圆柱体积)
- httpd+wildfly jboss集群搭建
- DRP学习之路--Filter实现设置字符集
- [并查集] hdu1325 Is it a tree ?
- 独木舟上的旅行
- 12、Hibernate映射set与List
- SQL Server 2008 学习笔记(三)视图的创建与修改
- 黑马程序员-C语言中有关宏的一些注意事项
- Servlet实现多文件上传2.0
- (easy)LeetCode 219.Contains Duplicate II