poj1328解题报告

来源:互联网 发布:桌面日历提醒软件 编辑:程序博客网 时间:2024/05/21 14:00

http://godfrey90.iteye.com/blog/1007578


1.算法 
本题是一道贪心题,和《算法艺术与信息学竞赛》中的“照亮的山景”题极为相似。 
(1)首先我们求出在每个岛屿放雷达以后在x轴上所能覆盖的区间,是在x轴的上的一个线段,即在这一段上放置雷达可以覆盖到该岛。 
(2)我们把每个岛对应的线段找出来,只要在这些线段上放置一些雷达,使得所有的线段上都有雷达即可符合题意(注意如果半径为0或者坐标的y轴小于半径的话将无法完成覆盖,输出-1)。 
(3)我们将线段根据左端点排序,找出如果一个线段包含另一个线段,则可以忽略外面的那一个线段(道理很简单),将其设为无效。 
(4)在剩下的线段中从左往右遍历,对于每个线段,尽量选取该线段的最右边的点作为雷达,如果之前有雷达在该线段上,则跳过该线段。 
(5)每次加一个雷达将计数器加一,最后可以得到解。 
2.实现 
(1)特别注意对于-1情况的判断,注意如果半径为0或者坐标的y轴小于半径的话将无法完成覆盖。 
(2)边读边判断的时候要确保改组所有的数据都读完才能输出-1继续下一组的处理。 
(3)在判断x轴上线段是否因为包含其他线段而无效时,可以从右往左遍历从而一次遍历完成判断。 
(4)在放置雷达时需要从左往右遍历,这里需要设置一个很小的doule值,以方便第一个雷达的选取,这个值要比integer的最小值的两倍还要小一点,故设为-5000000000。 

3.代码 

C++代码  收藏代码
  1. Problem: 1328       User: godfrey90  
  2. Memory: 368K        Time: 79MS  
  3. Language: G++       Result: Accepted  
  4.   
  5. #include <cstdio>  
  6. #include <cmath>  
  7.   
  8. struct unit {  
  9.     double h;  
  10.     double t;  
  11.     bool able;  
  12. };  
  13.   
  14. void work(int id,int m, int n);  
  15. bool get_ht(int r,int x,int y,double *ph,double *pt);  
  16. int main() {  
  17.     int m, n;  
  18.     int id=0;  
  19.     scanf("%d %d", &m, &n);  
  20.     while (!((m == 0) && (n == 0))) {  
  21.         work(id++,m, n);  
  22.         scanf("%d %d", &m, &n);  
  23.     }  
  24.     return 1;  
  25. }  
  26. void work(int id,int m, int n) {  
  27.     //init  
  28.     int x,y;  
  29.     unit arr[1000];  
  30.     int p = 0;  
  31.     bool flag = true;  
  32.     for (int i = 0; i < m; i++) {  
  33.         scanf("%d %d", &x, &y);  
  34.         if(!get_ht(n,x,y,&(arr[i].h),&(arr[i].t)))  
  35.             flag = false;  
  36.         arr[p++].able = true;  
  37.     }  
  38.     if(!flag){  
  39.         printf("Case %d: -1\n",id+1);  
  40.         return;  
  41.     }  
  42.     //sort  
  43.     int len = p;  
  44.     for (int i = 0; i < len; i++) {  
  45.         for (int j = i + 1; j < len; j++) {  
  46.             if (arr[i].h > arr[j].h) {  
  47.                 unit temp = arr[i];  
  48.                 arr[i] = arr[j];  
  49.                 arr[j] = temp;  
  50.             }  
  51.         }  
  52.     }  
  53.     //disable the useless one  
  54.     int tail = arr[len - 1].t;  
  55.     for (int i = len - 2; i >= 0; i--) {  
  56.         if (arr[i].t >= tail) {  
  57.             arr[i].able = false;  
  58.         } else {  
  59.             tail = arr[i].t;  
  60.         }  
  61.     }  
  62.     //find the radar  
  63.     int count = 0;  
  64.     double last = -5000000000;  
  65.     for (int i = 0; i < len; i++) {  
  66.         if ((arr[i].able) && (arr[i].h > last)) {  
  67.             count++;  
  68.             last = arr[i].t;  
  69.         }  
  70.     }  
  71.     printf("Case %d: %d\n",id+1,count);  
  72. }  
  73.   
  74. bool get_ht(int r,int x,int y,double *ph,double *pt){  
  75.     if((r<0)||(r*r-y*y<0)) return false;  
  76.     double dlt = sqrt(r*r-y*y);  
  77.     *ph = x-dlt;  
  78.     *pt = x+dlt;  
  79.     return true;  
  80. }  

原创粉丝点击