您的位置:首页 > 其它

NYOJ 喷水装置(二)贪心

2014-07-10 16:39 302 查看


喷水装置(二)

时间限制:3000 ms  |  内存限制:65535 KB
难度:4

描述有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。

输入第一行输入一个正整数N表示共有n次测试数据。

每一组测试数据的第一行有三个整数n,w,h,n表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。

随后的n行,都有两个整数xi和ri,xi表示第i个喷水装置的的横坐标(最左边为0),ri表示该喷水装置能覆盖的圆的半径。
输出每组测试数据输出一个正整数,表示共需要多少个喷水装置,每个输出单独占一行。

如果不存在一种能够把整个草坪湿润的方案,请输出0。
样例输入
2
2 8 6
1 1
4 5
2 10 6
4 5
6 5


样例输出
1
2


思路:把长方形问题转化成了区间A(线段A),求怎么用最少的小线段(L1,L2,L3,,,,,,Ln)才能全部覆盖线段A的问题 

本题出的很好,考验人的发散思维,,,,,come  on!!!!!!!!
#include<stdio.h> 

#include<algorithm> 

#include<math.h> 

using namespace std; 

const int MAX=10001;

struct p{ 

double left,right; 

}a[MAX]; 

bool cmp(struct p a,struct p b){ 

return a.left<b.left; 



int main() 



  int i,j,num,len,wight,times,count,biaoji; 

  double wight_2;    

  scanf("%d",×); 

  while(times--) 

  { 

    biaoji=1; 

    count=0; 

    scanf("%d%d%d",&num,&len,&wight); 

    wight_2=wight/2.000000; 

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

    { 

      int x,r; 

      double temp_w; 

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

      temp_w=sqrt(r*r-wight_2*wight_2); 

      if(temp_w>0)       // 排除r<=wight_2情况

      {                             //(a[0].right减去a[0].left)形成线段L0,最终 形成小线段(L1,L2,L3,,,,,,Ln) 

      a[i].left=x-temp_w;        

      a[i].right=x+temp_w;            

      }                                  

    } 

    sort(a,a+num,cmp);   //按照小线段L的左端点从小到大排序   

    double Max=0,sum=0;  //在使用本装置之前已经被覆盖的长度0 

    while(sum<len) 

    { 

      Max=0; 

      for(i=0;i<num&&a[i].left<=sum;i++) //本for循环每次找出a[i].left<=sum和 覆盖长度a[i].right-sum最长的一个; 

      {                                     

      if(a[i].right-sum>Max)Max=a[i].right-sum; 

      } 

      if(Max==0){biaoji=0; break; }//若有一次为0,表示找不到这条覆盖的线,也就是永远填满不了这条线 

      else{ count++; sum+=Max; } 

    } 

    if(biaoji) printf("%d\n",count); 

    else printf("0\n"); 

 } 

return 0; 



第二种解法:额,,,是别人的代码,,,不懂,,,坐等大神回复啊

#include<stdio.h>

#include<math.h>

#include<algorithm>

using namespace std;

struct p

{

double x;

double r;

}a[10004];

int cmp(p a,p b){return a.r<b.r;}//按照半径进行升序排列,排列后进行运算a[i].x=f-sqrt(g*g-h*h/4.0);a[i].r=sqrt(g*g-h*h/4.0)+f;的
                                                                    //顺序就完全乱了,后面的还怎么做??????

int main()

{

int t,n,w,h,i,j,x,r;

int f,g,l;

double max,sum;

scanf("%d",&t);

while(t--)

{

   scanf("%d%d%d",&n,&w,&h);

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

   {

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

    if(r>h/2.0)//排除r<=h/2.0无用情况 

    {

    a[j++].x=x;

    a[j-1].r=r;

    }

   }

   if(w<=h&&j==0){printf("0\n");continue;}

   if(w<=h&&j>0){printf("1\n");continue;}

   sort(a,a+j,cmp);//按照半径从小到大排序

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

   {

    f=a[i].x;

    g=a[i].r;

    a[i].x=f-sqrt(g*g-h*h/4.0);//(a[0].right-a[0].left)形成线段L0,

    a[i].r=sqrt(g*g-h*h/4.0)+f;   //a[i].x为L0的左端点坐标 , a[i].r为L0的左端点坐标

   } 

   l=0;max=0;sum=0;

   while(sum<w)

   {

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

    {

     if(a[i].x<=sum&&(a[i].r-sum>max))

       max=a[i].r-sum;

    }

    if(max==0)//注意这个地方,没有这个判断的话会超时

    {

      l=0;

      break;

    }

    sum+=max;

    l++;

    max=0;

   }

printf("%d\n",l);

}

return 0;

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