【计算机算法】贪心算法——喷水装置

喷水装置

题目

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

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

输入格式

输入包含若干组测试数据。

第一行一个整数T表示数据组数。

每组数据的第一行是整数n、L和W的值,其中n≤10 000。

接下来的n行,每行包含两个整数,给出一个喷头的位置和浇灌半径。

如图1所示的示意图是样例输入的第一组数据所描述的情况。

在这里插入图片描述

输出格式

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

输入样例

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

输出样例

6
2
-1

数据范围与提示

对于100%的数据,n≤15000。

程序代码

#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
#define MAXN 10000

int n;//喷头个数
double L,W;//草坪长度和宽度
int cnt;

struct nozzle{
    
    
	double location;
	double radius;
	double front_location;
	double behind_location;
}nozzles[MAXN]; 

bool cmp(nozzle a,nozzle b){
    
    
	return a.front_location<b.front_location;
}

void input(){
    
    
	scanf("%d %lf %lf",&n,&L,&W);
	int i = 0;
	for(i;i < n;i++){
    
    
		scanf("%lf %lf",&nozzles[i].location,&nozzles[i].radius);
		if(nozzles[i].radius <= W/2)
        	continue;
        cnt++;
		nozzles[i].front_location = nozzles[i].location - sqrt(nozzles[i].radius*nozzles[i].radius - W*W/4.0);
		nozzles[i].behind_location = nozzles[i].location + sqrt(nozzles[i].radius*nozzles[i].radius - W*W/4.0);
	}
	sort(nozzles,nozzles + cnt,cmp);
}

void caculate(){
    
    
	int min = 0,i=0;
	double sum = 0;
	bool flag = true;
	while(sum < L){
    
    
		min ++;
		double temp = sum;
		for(i = 0;nozzles[i].front_location <= temp && i <= cnt;i++){
    
    
			if(sum < nozzles[i].behind_location){
    
    
				sum = nozzles[i].behind_location;
			}
		}
		if(temp == sum && temp < L){
    
    
			cout<<"-1"<<endl;
			flag = false;
			break;
		}
	}
	if(flag)
		cout<<min<<endl;
}

int main(){
    
    
	int count = 0;
	cin>>count;
	while(count > 0){
    
    
		input();
		caculate();
		count--;
	}
}

猜你喜欢

转载自blog.csdn.net/passer__jw767/article/details/110941381