Chinaunix首页 | 论坛 | 博客
  • 博客访问: 482424
  • 博文数量: 59
  • 博客积分: 345
  • 博客等级: 二等列兵
  • 技术积分: 1380
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-18 22:44
个人简介

to be myself

文章分类

全部博文(59)

文章存档

2017年(5)

2013年(47)

2012年(3)

2011年(4)

分类: C/C++

2013-03-02 17:23:45

先说下我刚开始错误的想法:本想用与一般人不一样的方法,即按岛屿的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的右最为衡量标准了.
        因为这样可以左移最右坐标, 可以让可能更多的岛屿被侦测到(他们的最左与衡量标准有更多的交集)
        具体实现看代码 


点击(此处)折叠或打开

  1. #include <math.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. #define MAX 1001

  5. typedef struct
  6. {
  7.     double xl; //最左可被侦测坐标
  8.     double xr; //最右可被侦测坐标
  9. }coordinate;

  10. coordinate island[MAX]={0};

  11. //按xl递减排序
  12. int cmp(const void* a, const void *b)
  13. {
  14.     return ((coordinate *)a)->xl > ((coordinate *)b)->xl ? 1 : -1;
  15. }

  16. /******************************************************
  17. |func: 贪婪算法找最少雷达数
  18. |args: 岛屿可被侦测坐标island,岛屿数n,雷达侦测半径d
  19. |retn: 可侦测所有岛屿的最少雷达数
  20. ******************************************************/
  21. int Greedy(coordinate island[], int n, int d)
  22. {
  23.     int num = 0, i;
  24.     double cur; //当前最右可被侦测坐标
  25.     
  26.     cur = island[0].xr;
  27.     num++;
  28.     
  29.     for (i=1; i<n; i++)
  30.     {
  31.         if (island[i].xl - cur > 1e-5) //下个岛屿的最左坐标大于当前最右可被侦测坐标
  32.         {
  33.             num++;
  34.             cur = island[i].xr;
  35.         }
  36.         else
  37.         {
  38.             if (island[i].xr - cur < 1e-5) //下个岛屿的最右坐标小于当前最右可被侦测坐标
  39.             {
  40.                 cur = island[i].xr;
  41.             }
  42.         }
  43.     }
  44.     return num;
  45. }

  46. int main()
  47. {
  48.     int i, n, d, x, y, count = 0, flag = 0;
  49.     double offset;
  50.     
  51.     while(scanf("%d %d", &n, &d) == 2 && !(n==d && 0==d))
  52.     {
  53.         flag = 0;
  54.         count++;
  55.         
  56.         for (i=0; i<n; i++)
  57.         {
  58.             scanf("%d %d", &x, &y);
  59.             if (y > d)
  60.             {
  61.                 flag = 1;
  62.             }
  63.             offset = sqrt((double)(d * d - y * y));
  64.             island[i].xl = x - offset;
  65.             island[i].xr = x + offset;
  66.         }
  67.         if (flag)
  68.         {
  69.             printf("Case %d: -1n", count);
  70.             continue;
  71.         }
  72.         
  73.         qsort(island, n, sizeof(island[0]), cmp);
  74.         i = Greedy(island, n, d);
  75.         printf("Case %d: %dn", count, i);
  76.     }
  77.     return 0;
  78. }
Problem: 1328  User: angrad 
      Memory: 156K  Time: 0MS 
      Language: C  Result: Accepted


2011-03-24 22:04 发表于百度空间,今搬至CU。

阅读(7126) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

HeyShirley2015-05-16 09:40:49

假定当前的岛屿为cur,当前的下一个为next。
   1.如果next的最左可被侦测坐标比cur的最右都大的话,只能再设一个雷达来侦测next了。
   2.如果next的最左可被侦测坐标比cur的最右小,这时会有两种情况。
          A.next最右 < cur最右
         B.next最右 >= cur最右
       对于B情况,我们可以直接侦测到next了, 可以找next的next了.
       对于A情况,也就等价于next包含于cur, 这样就应该把next的右最为衡量标准了.

*****************************************************************

angrad2014-08-14 21:09:30

zjhzxhz:这表述实在是理解不能啊~

1. 这就可以分别确定雷达相对与岛屿x的最左坐标和x最右坐标。
   最左为:x - sqrt(d*d-y*y); 最右为:x - sqrt(d*d-y*y); 

   请问表达式中的x是什么? 岛屿的最左坐标吗?

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

   请问cur和next是什么? 岛屿的x坐标? 这指代也太不明确了吧~

谢谢你的留言。
这个很久没看了,说下我现在的理解吧。
首先更正一下文中的错误“最右为:x - sqrt(d*d-y*y); ”应为“最右为:x + sqrt(d*d-y*y); ”
1.从程序可以看出,x - sqrt(d*d-y*y);表达式中的x,y是指每一个岛的x,y坐标。island[i].xl这个才是可能的岛屿的最左坐标。
2.cur、next并不是指岛屿的x坐标,而是指代岛屿这个单位。

回复 | 举报

zjhzxhz2014-08-13 10:51:44

这表述实在是理解不能啊~

1. 这就可以分别确定雷达相对与岛屿x的最左坐标和x最右坐标。
   最左为:x - sqrt(d*d-y*y); 最右为:x - sqrt(d*d-y*y); 

   请问表达式中的x是什么? 岛屿的最左坐标吗?

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

   请问cur和next是什么? 岛屿的x坐标? 这指代也太不明确了吧~