llg的农场(farm)

  评测传送门

【题目描述】

llg 是一名快乐的农民,他拥有一个很大的农场,并且种了各种各样的瓜果蔬菜,到了每年秋天,他就可以把所有蔬菜水果卖到市场上,这样他就可以获利。但今年他遇到了一个难题——有许多鸟来到了他的农场偷吃他的瓜果蔬菜。不知所措的 llg 只好求助于 jump,万能的 jump 于是给了 llg 一些稻草人(据说可以驱鸟)。每个庄稼都可以看做是坐标系里面的一个点,当它处于某个稻草人的范围内时就可以视为被保护。可是每个稻草人的辐射范围有限,根据测定,每个稻草人的辐射范围都是一个半径为 R 的圆,llg 很懒,所以他只打算把稻草人放在坐标系的 x 轴上,而任何庄稼(x,y)都满足 y>0。图中的小红点就是庄稼,蓝点即稻草人放的位置。现在请你来帮助 llg设计一个方案,用尽可能少的稻草人来保证所有庄稼都是安全的。若存在无法覆盖的庄稼或者 jump 给的稻草人不够覆盖所有庄稼,请输出-1。

 


【输入数据】
每个测试点含多组数据
每组数据第一行包含 n,R,C;分别表示庄稼的数量、稻草人的最大覆盖半径,命题人:黎锦灏
稻草人的数量。
接下来 n 行,每行包括两个数 xi,yi 表示一个点的坐标
输入以“0 0 0”结尾


【输出数据】
对于每组数据,请输出最小要用多少稻草人,才能保证覆盖所有庄稼。若无法覆
盖或数量不够,请输出-1。

 

【数据约定】
对于 30%的数据,1<=n<=3000
对于 100%的数据, 1<=n<=50000,1<=数据组数<=10,其余数据均保证不会超过 int的范围

 

思路:

  对于任意一个庄稼 我们可以很轻松的得出能覆盖到此庄稼的的稻草人位置 即圆心位置

  令庄稼位置为(x,y)

  则稻草人的横坐标范围为[x-sqrt(r*r-y*y),x+sqrt(r*r-y*y)] 边界就是庄稼恰好在圆心上

  我们求出每个庄稼所对应的圆心范围后 题目就转化成了:

  有若干可能互相重合的线段 求最少的点数使每条线段上至少有一点

  然后按横坐标排序

  贪心 对于排序之后的线段 取最右端为最优(尽可能覆盖到多的点)

  具体见代码吧

 

CODE:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #define go(i,a,b) for(register int i=a;i<=b;i++)
 6 #define db double
 7 #define M 50000+10
 8 using namespace std;
 9 int read()
10 {
11     int x=0,y=1;char c=getchar();
12     while(c<'0'||c>'9') {if(c=='-') y=-1;c=getchar();}
13     while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
14     return x*y;
15 }
16 int n,r,m,x,y,ans;
17 bool fg;
18 struct node {db l,r;}a[M];
19 bool cmp(node u,node v){if(u.l!=v.l) return u.l<v.l;return u.r<v.r;}
20 int main()
21 {
22     freopen("1.in","r",stdin);
23     freopen("1.out","w",stdout);
24     while(1)
25     {
26         n=read();r=read();m=read();ans=1;fg=0;
27         if(!n&&!r&&!m) return 0;
28         go(i,1,n)
29         {
30             x=read();y=read();
31             if(y>r||fg) {fg=1;continue ;}
32             db k=(db)sqrt(r*r-y*y);
33             a[i].l=(db)x-k;
34             a[i].r=(db)x+k;
35         }
36         if(fg) {puts("-1");continue ;}
37         sort(a+1,a+n+1,cmp);
38         db nw=a[1].r;
39         go(i,2,n)
40         {
41             if(a[i].l>nw) {ans++;nw=a[i].r;}
42             else nw=min(nw,a[i].r);
43         }
44         if(ans>m) {puts("-1");continue ;}
45         printf("%d\n",ans);
46     }
47     return 0;
48 }
View Code

 

转载于:https://www.cnblogs.com/forward777/p/10338294.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值