您的位置:首页 > 其它

喷水装置(二)(最小线段覆盖)

2015-09-12 12:21 337 查看
题目地址

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

解题思路:先将没用的装置(半径<h/2)去掉,再用贪心选择最合适的

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <stack>

using namespace std;

const int maxn = 1e4+100;

struct Circle
{
double l,r;
}cir[maxn];

bool cmp(Circle a,Circle b)
{
if(a.l == b.l) return a.r> b.r;
return a.l < b.l;
}

int main()
{
int t,n,cnt;
double x,y,w,h;
scanf("%d",&t);
while(t--)
{
scanf("%d%lf%lf",&n,&w,&h);
double minn = 0xffffff;
double maxx = 0;
cnt = 0;
for(int i = 0; i < n; i++)
{
scanf("%lf%lf",&x,&y);
if(y>=h/2)
{
cir[cnt].l = x-sqrt(y*y-h*h/4);
cir[cnt].r = x+sqrt(y*y-h*h/4);
minn = min(minn,cir[cnt].l);
maxx = max(maxx,cir[cnt].r);
cnt++;
}
}
if(minn > 0 || maxx < w)
{
puts("0");
continue;
}
sort(cir,cir+cnt,cmp);
double l=0,r=0;
int flag = 0;
maxx = 0;
int ans = 0;
while(r < w)
{
l = cir[flag].l;
r = cir[flag].r;
for(int i = 0; i < cnt; i++)
{
if(cir[i].l <= maxx && cir[i].r > r)
{
l = cir[i].l;
r = cir[i].r;
flag = i;
}
}
flag++;
maxx = max(maxx,r);
ans++;
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: