描述
有一块草坪,横向长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
分析:
告诉你喷水的位置和喷射的半径,你可以求出能覆盖矩形草坪在水平方向上的长度,即知道每个喷水的左右端点,剩下的就是求在固定区间内问最少多少个小区间能够覆盖
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <string>
using namespace std;
double len(double a,double b)
{
return sqrt(a*a-b*b);
}
int cmp(pair<double,double>a,pair<double,double>b)
{
return a.first < b.first;
}
int main()
{
int t;
cin >> t;
while(t--)
{
int n,w,h;
cin >> n >> w >> h;
vector<pair<double,double> >v;
for(int i = 0;i < n;i++)
{
int x,r;
cin >> x >> r;
double l = len(r,h/2.0);
if(l > h/2.0)
{
pair<double,double>p;
p.first = x-l;
p.second = x+l;
v.push_back(p);
}
}
sort(v.begin(),v.end(),cmp);
int cnt = 0;
double right = 0;
while(right < w)
{
double m = 0.0;
///求尽可能在已知区间上向右扩展的最大的右端点,使得尽可能使用较少的喷水器就能全部覆盖
for(int i = 0;i < v.size()&&v[i].first <= right;i++)
{
if(v[i].second - right > m)m = v[i].second - right;
}
if(m)
{
cnt++;
right+=m;
}
else
break;///如果扩展不动了,那就说明已经扩展完成了
}
if(right < w)
cout << 0 << endl;
else
cout << cnt << endl;
}
return 0;
}
哈
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <string>
using namespace std;
double len(double a,double b)
{
return sqrt(a*a-b*b);
}
int cmp(pair<double,double>a,pair<double,double>b)
{
return a.first < b.first;
}
int main()
{
int t;
//ios::sync_with_stdio(false);
cin >> t;
while(t--)
{
int n,w,h;
//cin >> n >> w >> h;
scanf("%d%d%d",&n,&w,&h);
vector<pair<double,double> >v;
for(int i = 0;i < n;i++)
{
int x,r;
//cin >> x >> r;
scanf("%d%d",&x,&r);
double l = len(r,h/2.0);
if(l > h/2.0)
{
pair<double,double>p;
p.first = x-l;
p.second = x+l;
v.push_back(p);
}
}
sort(v.begin(),v.end(),cmp);
int cnt = 0;
double right = 0;
int top = 0;
while(right < w)
{
double be = right+0.000001;///每次加上0.000001,俩区间有断点,就能区分
for(int i = top;i < v.size();i++)
{
if(v[i].first <= be&&v[i].second >= be)
{
right = v[i].second > right ? v[i].second:right;
}
else if(v[i].first > be)
{
top = i;
break;
}
}
if(be > right) break;
else cnt++;
}
if(right < w)
//cout << 0 << endl;
printf("0\n");
else
//cout << cnt << endl;
printf("%d\n",cnt);
}
return 0;
}