您的位置:首页 > 其它

UVA 10382 贪心 最少圆

2017-09-13 16:30 323 查看
题目:https://cn.vjudge.net/contest/170620#problem/A

给你一块草地,有长,宽,给你n个喷头,每个喷头给出中心和喷洒范围。求覆盖这片草地的最小碰头数量。

思路:这是经典的贪心题,从左到右,把所有喷头排序,现在第一个喷头的最右边距离为right,找到剩下喷头中喷头能覆盖right的,且喷头右边的距离最大的喷头,然后更新最右边的距离right。

这里注意计算喷头覆盖的距离时不能直接取半径,要用下余弦定理。半径小于草地的宽的一半的喷头直接报废。

#include<iostream>
#include<cmath>
#include<algorithm>
#include<stdio.h>
using namespace std;
struct node {
double x,y;
}a[10005];
bool cmp(node a, node b)
{
if (a.x < b.x)
return 1;
return 0;
}
int main()
{
int n, l, w,i,j;
double z, r;
while (~scanf("%d%d%d", &n, &l, &w))
{
int temp=0;
for ( i = 0; i < n; i++)
{
scanf("%lf%lf", &z,&r);
if (r <= w / 2)
continue;
double t = sqrt(r*r - w*w / 4.0);
a[temp].x = z - t;
a[temp].y = z + t;
temp++;//把每个喷头的覆盖范围计算出来
}
sort(a, a + temp, cmp);
double left = 0, right = 0;int sum = 0;
if (a[0].x <= 0)
{
for (i = 0; i < temp;)
{
for (j = i; j < temp&&a[j].x <= left; j++)//覆盖到left的喷头里选择最大right
{
if (a[j].y > right)
right = a[j].y;
}
if (j == i)
break;
left = right;
i = j;
sum++;
if (left >= l)
break;
}
}
if (left >= l)
cout << sum << endl;
else
cout << -1 << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  贪心