您的位置:首页 > 其它

喷水装置-(二)

2016-07-19 19:54 190 查看
题目链接:这里看原题目

题目:


喷水装置(二)

时间限制: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


来源《算法艺术与信息学竞赛》
这是一道黑书上的题目,在这道题目之前先看一道比较简单的题目:


喷水装置(一)

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

描述现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会让以它为中心的半径为实数Ri(0<Ri<15)的圆被湿润,这有充足的喷水装置i(1<i<600)个,并且一定能把草坪全部湿润,你要做的是:选择尽量少的喷水装置,把整个草坪的全部湿润。

输入第一行m表示有m组测试数据

每一组测试数据的第一行有一个整数数n,n表示共有n个喷水装置,随后的一行,有n个实数ri,ri表示该喷水装置能覆盖的圆的半径。
输出输出所用装置的个数
样例输入
2
5
2 3.2 4 4.5 6
10
1 2 3 1 2 1.2 3 1.1 1 2


样例输出
2
5


来源[苗栋栋]原创
上传者苗栋栋
题目的意思就是说现在有一个2*20米的草坪,有n个喷水装置,每个喷水装置洒水所能覆盖的范围为一个半径为r的圆,问至少需要多少个喷水装置,能够把草坪全部喷湿。很明显,把喷水装置放在中轴线上最划算,如果喷水装置的半径小于1米,就可以认为这个喷水装置是无用的,因为直径小于2米,纵向的不能完全覆盖,那就没什么用了。这样分析后,可以计算出每个喷水装置所能覆盖的横向的范围,也就是2*sqrt(r*r-1),把这些长度按照从大到小的顺序排序,贪心选择就可以了。
再看第二题,这个时候装置的位置是固定的,所能覆盖的范围为[ l , r ],很明显如果最小的 l 大于0或者最大的r小于w,那么是无解的,同样如果有的 l < 0 那么可以令l = 0,小于0的部分是“用不到”的,大于w的部分是“用不到”的。下面就是如何选择的问题,把 l 按照从小到大的顺序排,如果l相同,r越大越好,因为同样的l,r越大覆盖的范围越大。设当前能够覆盖的坐标为L,初始L=0,要在未使用的喷水装置中选择符合条件:l<=L,并且其r最大的一个喷水装置,这样才是最省的。如果剩下所有装置的 l > L ,就是无解的。
代码:
#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<cstdio>
#include<stdlib.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define in(a) scanf("%d",&a)
#define mm(a,b) memset(a,b,sizeof(a))
#define out(a) printf("%d\n",a)
#define MOD 1e9+7
#define ll long long
#define INF 0x3f3f3f3f
#define FOR(i,l,r) for(int i=l;i<=r;i++)

const int N = 10010;

struct node
{
double l,r;
};
node a
;
int cmp(node x,node y)
{
if(x.l==y.l)
return x.r>y.r;
return x.l<y.l;
}

double h,w;
int n;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
cin>>n>>w>>h;
int cnt=0;
for(int i=0;i<n;i++)
{
double x,R;
cin>>x>>R;
if(R<=h/2)
continue;
double k=sqrt(R*R-h*h/4);
a[cnt].l=x-k;
a[cnt].r=x+k;
if(a[cnt].l<0)
a[cnt].l=0;
if(a[cnt].r>w)
a[cnt].r=w;
cnt++;
}
sort(a,a+cnt,cmp);
bool ok=true;
int ans=0;
double L=0;
int i=0;
while(i<cnt)
{
if(L>=w)
break;
if(a[i].l>L)
{
ok=false;
break;
}
double temp=0;
while(i<cnt&&a[i].l<=L)
{
temp=max(temp,a[i].r);
i++;
}
L=temp;
ans++;
}
if(ok&&L>=w)
cout<<ans<<endl;
else cout<<0<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: