uva10382 - Watering Grass(区间覆盖变形)

题目:uva10382 - Watering Grass(区间覆盖变形)

题目大意:要给一片草坪浇水,给定草坪的长度和宽度,给出每个喷头的圆心C和喷水的半径R,问最少要几个喷头可以给整片草坪都浇上水。

解题思路:区间覆盖问题的变形,因为草坪有宽度W,所以这个每个喷头的有效范围是[C- sqrt(R* R - 0.25 * W * W   ,  C + sqrt (R*R - 0.25 * W *W)].

代码:

#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string.h>
using namespace std;

const int N = 10005;
int n, l, w;
int visit[N];

double Max (const double a, const double b) { return a > b ? a: b; }

struct Len {

	double L, R;
}len[N];

int cmp (const Len &a, const Len &b) { return a.L < b.L;}

void handle (int c, int r, int i) {

	double r1 = r;
	double c1 = c;
	double w1 = w;
	double temp = sqrt (r1 * r1 - 0.25 * w1 * w1);
	len[i].L = c - temp;
	len[i].R = c + temp;
}

int solve () {

	memset (visit, 0, sizeof (visit));
	if (len[0].L > 0)
		return -1;
	double s = 0;
	double ll = -1;
	int m = -1;
	for (int i = 0; i < n; i++) {

		if (len[i].L <= s) {

			if (ll < len[i].R) {

				visit[i] = 1;
				if (m >= 0)
					visit[m] = 0;
				m = i;
				ll = Max (ll, len[i].R);
			}
		} else {

			if (s == ll)
				return -1;
			s = ll;
			i--;
			m = -1;
		}
//		printf ("%f\n", ll);
	}
//	printf ("%f\n", ll);
	if (ll < l)
		return -1;
	int count = 0;
	for (int i = 0; i < n; i++)
		if (visit[i])
			count++;
	return count;
}

int main () {

	int c, r;
	while (scanf ("%d%d%d", &n, &l, &w) != EOF) {

		for (int i = 0; i < n; i++) {

			scanf ("%d%d", &c, &r);
			handle (c, r, i);
		}
		sort (len, len + n, cmp);

/*		for (int i = 0; i < n; i++)
			printf ("%f %f\n", len[i].L, len[i].R);*/
		printf ("%d\n", solve());

	}
	return 0;
}
时间: 2024-08-06 16:03:33

uva10382 - Watering Grass(区间覆盖变形)的相关文章

UVA10382- Watering Grass(区间覆盖问题)

题意:一块长l,宽w的长方形草坪,在其中心线的不同位置处装有n个点状的喷水装置.每个喷水装置i可将以它为中心,半径为ri的圆形区域润湿.请选择尽量少的喷水装置,把整个草坪全部润湿. 思路:变形的区间覆盖问题.其实我们只要将圆形转化为覆盖在草坪上的矩形即可.当半径ri<w/2时,圆形面积在草坪真正有用的只是一条竖线,对于完全覆盖草坪没有任何意义,所以这种喷水装置不取.转化完之后,只要按照区间覆盖问题去解决就行了.先判断是否能从开头开始覆盖,之后每次取起点相同,但是区间长度最长的那个区间(期间注意判

区间选点+区间覆盖

区间选点+区间覆盖 区间选点问题(选择最少的点,使得每个区间都至少有k个点) 将这些区间[l,r]先按照r从小到大排序,再按照l从大到小排序.选点尽量选择靠近右边界的点.然后按照这个排序后的区间进行遍历,用一个变量来存放遍历过程中上个区间的右边界,然后碰到一个新的区间的时候需要分两种情况讨论:1.这个区间和上个区间有相交的部分,那么就需要判断一下上次选择的点有多少在这个区间内,这些点满足要求吗?不满足的话还需要在这个区间内选点2.这个区间和上个区间没有交集,那么这个区间就需要选点. 上述策略可以

10382 - Watering Grass(贪心 区间覆盖问题)洒水面覆盖

double qiuzhi(int id) { double t1=cc[id].rid*cc[id].rid; double t2=w*w/4; double t3=t1-t2; double t4=sqrt(t3); return t4; } void to_qujian() { for(int i=0; i<t; i++) { double zhi=qiuzhi(i); qq[i].a=cc[i].pos-zhi; qq[i].b=cc[i].pos+zhi; } } 典型的贪心区间覆盖问

UVa 10382 Watering Grass (区间覆盖贪心问题+数学)

题意:有一块长为l,宽为w的草地,在其中心线有n个喷水装置,每个装置可喷出以p为中心以r为半径的圆, 选择尽量少的装置,把草地全部润湿. 析:我个去啊,做的真恶心,看起来很简单,实际上有n多个坑啊,首先这个题,应该可以看出来是贪心算法, 具体的说是区间覆盖问题,这个问题总体来说不难,但是在这有了巨多的坑.要注意以下几点: 1.这是一个草坪,不是线段,首先你要先把实验室转化为线段. 2.这个喷水装置喷出是圆,不是矩形,要运用数学知识进行运算. 3.输入的半径的两倍如果小于等于宽度,就得忽略不记.因

UVA 10382 Watering Grass(区间覆盖,贪心)题解

题意:有一块草坪,这块草坪长l 米,宽 w 米,草坪有一些喷头,每个喷头在横坐标为 p 处,每个喷头的纵坐标都是(w/2) ,并且喷头的洒水范围是一个以喷头为圆心,半径为 r 米的圆.每次最少需要打开多少个喷头来给草坪洒水,并且草坪各处都能被洒到,不行输出-1 思路:这是一道区间覆盖(贪心)题: 有一堆区间 l1, r1:l2, r2...ln,rn,问你最少用几个能覆盖0~P的长度 那么我们先按照L升序排序,far是目前所能找到的最远处,R是上一次查询所能找到的最远处,每次查询我们都要找后面满

uva 10382 - Watering Grass(区域覆盖问题)

Sample Input 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 题目大意: 有一块草坪,长为l,宽为w,在它的水平中心线上有n个位置可以安装喷水装置,各个位置上的喷水装置的覆盖范围为以它们自己的半径ri为圆.求出最少需要的喷水装置个数. 分析与总结: 这题的关键在于转化 根据这图可以看出,一个喷水装置的有效覆盖范围就是圆中间的那个矩

uva 10382 Watering Grass(贪心)

uva 10382 Watering Grass n sprinklers are installed in a horizontal strip of grass l meters long and w meters wide. Each sprinkler is installed at the horizontal center line of the strip. For each sprinkler we are given its position as the distance f

UVa 10382 - Watering Grass 解题心得

原题: n sprinklers are installed in a horizontal strip of grass l meters long and w meters wide. Each sprinkler is installed at the horizontal center line of the strip. For each sprinkler we are given its position as the distance from the left end of t

ural Minimal Coverage (区间覆盖)

http://acm.timus.ru/problem.aspx?space=1&num=1303 给出一些区间,选择尽量少的区间能覆盖到[0,m]. 小白p154,典型的区间覆盖问题.一直在想怎么dp.. 首先预处理,先按左端点从小到大排序,若左端点相同右端点从大到小排序,若区间x完全包含y,按照贪心的思想,y是没有意义的,有大区间可以选何必选择小区间.处理完事之后各个区间满足a1 <= a2 <= a3....且b1 <= b2 <= b3... 这样找到第一个覆盖0的