贪心算法之喷水装置问题

Description
长 L 米,宽 W 米的草坪里装有 n 个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 W/2  米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。

请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?

Input
输入包含若干组测试数据。
第一行一个整数 T, 表示数据组数;
每组数据的第一行是整数 n、L 和 W,n≤15000;
接下来的 n 行,每行包含两个整数,给出一个喷头的位置和浇灌半径(上面的示意图是样例输入第一组数据所描述的情况)。

Output
每组测试数据的输出占一行,每行输出一个数字,表示要浇灌整块草坪所需喷头数目的最小值。如果所有喷头都打开也不能浇灌整块草坪,则输出 -1 。

Sample Input 

3
8 20 2
5 3
4 1
1 2
7 2
10 2
13 3
16 2
19 4
3 10 1
3 5
9 3
6 1
3 10 1
5 3
1 1
9 1

Sample Output
6
2
-1

思路:很明显的贪心问题,因为是一块草地,所以要考虑长和宽,宽的话只需要在输入数据的时候考虑一下半径,如果半径小于等于宽的二分之一就直接略过,在考虑长的时候不能以喷水的最长去考虑,要考虑和草地的交点,同时要考虑交点和交点之间要连起来或者互相覆盖,交点的计算公式为:start=x-sqrt(radius^2-(w/2)^2),end=
x+sqrt(radius^2-(w/2)^2),并把最后一个end求出来,如果大于长,就说明可以,否则输出-1.

代码如下:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
using namespace std;
#define MAX_NUM 15001

typedef struct Sprayer{
 double location;
 double radius;
 double inter_point_start;
 double inter_point_end;
}Spr[MAX_NUM];

int cmp(Sprayer a,Sprayer b){
    return a.inter_point_start<b.inter_point_start;
}

int main()
{
  int T;
  Spr spr;
  cin>>T;
  for(int i=1;i<=T;i++){
    int n,cnt = 0;
    double L,W;
    cin>>n>>L>>W;
    for(int i=1;i<=n;i++){
       cin>>spr[i].location>>spr[i].radius;
       if(spr[i].radius <= W/2)
        continue;
        //cout<<"jiance"<<endl;
        cnt++;
       spr[cnt].inter_point_start = spr[i].location-sqrt(spr[i].radius*spr[i].radius-W*W/4.0);//cout<<"a[cnt].x"<<"Ϊ"<<spr[cnt].inter_point_start<<endl;
       spr[cnt].inter_point_end = spr[i].location+sqrt(spr[i].radius*spr[i].radius-W*W/4.0);//cout<<"a[cnt].x"<<"Ϊ"<<spr[cnt].inter_point_end<<endl;
    }
    sort(spr+1,spr+cnt+1,cmp);
    //cout<<"jiance2"<<endl;
    int min_num = 0;
    double Sum = 0;
    int flag = 1;
    int i=1;
    while(Sum < L){
        min_num++;
        double t = Sum;
        for(;spr[i].inter_point_start <= t && i<=cnt;i++)//
            if(Sum < spr[i].inter_point_end)
             {
                 Sum = spr[i].inter_point_end;
                 //cout<< Sum<<"是多少";
             }
            if(t==Sum && t<L){
              cout<<"-1"<<endl;
              flag = 0;
              break;
            }
        }

    if(flag)
        cout<<min_num<<endl;

  }

}
发布了69 篇原创文章 · 获赞 50 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq873044564/article/details/88893701