喷水装置二---耗时两天,感觉只是会这道题而已,区间贪心

2024-04-23 14:32

本文主要是介绍喷水装置二---耗时两天,感觉只是会这道题而已,区间贪心,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=12

题目:

喷水装置(二)

时间限制:3000 ms  |  内存限制:65535 KB
难度:4
描述
有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。
输入
第一行输入一个正整数N表示共有n次测试数据。
每一组测试数据的第一行有三个整数n,w,h,n表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。
随后的n行,都有两个整数xi和ri,xi表示第i个喷水装置的的横坐标(最左边为0),ri表示该喷水装置能覆盖的圆的半径。
输出
每组测试数据输出一个正整数,表示共需要多少个喷水装置,每个输出单独占一行。
如果不存在一种能够把整个草坪湿润的方案,请输出0。
样例输入
2
2 8 6
1 1
4 5
2 10 6
4 5
6 5
样例输出
1
2

思路:

这道题,测试用例都是费的,我之前的做法就一直是wrong answer.测试用例过了,不代表能过。最主要是把问题分析好。很明显就是排序,然后不断的试,看是否符合条件

(贪心)。。但是关键就是在这个条件的判断。


从这里http://blog.csdn.net/pointerking/article/details/22686001    了解到了该怎么解决,虽然耗尽心思,觉得懂了,但不担保,同类型的会动。只是觉得很神奇,很佩服想

到是怎么做的。不买关子先,直接解释下。。

首先对读入的数据要做一次判断:

if(NodeArrArr[i].r<=h/2){		//不能构成一个完整的三角形,斜边要大于直角边i--;n--;continue;}

也就是半径要大于直角边:



只有构成了这种情况,才能临界覆盖整个长方向。

接着:

NodeArrArr[i].left=NodeArrArr[i].x-Math.sqrt(NodeArrArr[i].r*NodeArrArr[i].r-h*h/4);

将情况分为left和right。

left有三种情况



==0,是临界,<0肯定是可以的,>0肯定不满足


而右边的情况:NodeArrArr[i].right=NodeArrArr[i].x+Math.sqrt(NodeArrArr[i].r*NodeArrArr[i].r-h*h/4);

只有大于长度w的情况,和<w的情况。


感觉自己还是讲得不够清楚,可以讲案例的数据带进去,模拟下,画下图就可以理解了。进行实践才是最好的学习方式。

import java.util.Scanner;
/** 170	 662	* 喷水装置二*/
public class Main1{public static void main(String[] args){Scanner sc=new Scanner(System.in);int m=sc.nextInt();while(m-->0){int n=sc.nextInt();double w=sc.nextDouble();double h=sc.nextDouble();NodeArr[] NodeArrArr=new NodeArr[n];for(int i=0;i<n;i++){NodeArrArr[i]=new NodeArr();NodeArrArr[i].x=sc.nextDouble();NodeArrArr[i].r=sc.nextDouble();if(NodeArrArr[i].r<=h/2){		//不能构成一个完整的三角形,斜边要大于直角边i--;n--;continue;}//NodeArrArr[i].r*NodeArrArr[i].r-h*h/4--得到刚好能覆盖长方形的情况,看是否给出的数据符合NodeArrArr[i].left=NodeArrArr[i].x-Math.sqrt(NodeArrArr[i].r*NodeArrArr[i].r-h*h/4);NodeArrArr[i].right=NodeArrArr[i].x+Math.sqrt(NodeArrArr[i].r*NodeArrArr[i].r-h*h/4);}NodeArrArr=insertSort(NodeArrArr,n);	//直接插入排序,从大到小int count=0;int flag=0;double max=0,begin=0;for(int i=0;i<n;i++){while(i<n&&NodeArrArr[i].left<=begin){	//由最大的开始,负数,就一定可以覆盖,就左边而言if(NodeArrArr[i].right>max)		//在上面的情况下,找到最大的--right=x+need,下面的与w判断max=NodeArrArr[i].right;i++;}i--;			//不怕越界,后面有判断出去的。//每次都要判断一下Max的值,看是否已经出界,若出界则跳出,否则继续贪心if(max>=w){count++;begin=max;break;}else if(begin<max){	 //Max不出界,则正常向右贪心count++;begin=max;}else{			//两点以上的中间会有断点flag=1;break;}}if(flag==1||begin<w){		//右边盖不住  System.out.println("0");}else{System.out.println(count);}}}public static NodeArr[] insertSort(NodeArr[] arr,int length){double key1,key2;for(int i=1;i<length;i++){int j=i-1;key1=arr[j].left;key2=arr[j].right;while(j>0&&key1<arr[j-1].left){arr[j].left=arr[j-1].left;arr[j].right=arr[j-1].right;j--;}arr[j].left=key1;arr[j].right=key2;}return arr;}}
class NodeArr{double x,r,left,right;
}

最后补充下知识点--区间的贪心:http://shu-mj.com/archives/167



这篇关于喷水装置二---耗时两天,感觉只是会这道题而已,区间贪心的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/929053

相关文章

电力系统中的A类在线监测装置—APView400

随着电力系统的日益复杂和人们对电能质量要求的提高,电能质量在线监测装置在电力系统中得到广泛应用。目前,市场上的在线监测装置主要分为A类和B类两种类型,A类和B类在线监测装置主要区别在于应用场景、技术参数、通讯协议和扩展性。选择时应根据实际需求和应用场景综合考虑,并定期维护和校准。电能质量在线监测装置是用于实时监测电力系统中的电能质量参数的设备。 APView400电能质量A类在线监测装置以其多核

usaco 1.3 Barn Repair(贪心)

思路:用上M块木板时有 M-1 个间隙。目标是让总间隙最大。将相邻两个有牛的牛棚之间间隔的牛棚数排序,选取最大的M-1个作为间隙,其余地方用木板盖住。 做法: 1.若,板(M) 的数目大于或等于 牛棚中有牛的数目(C),则 目测 给每个牛牛发一个板就为最小的需求~ 2.否则,先对 牛牛们的门牌号排序,然后 用一个数组 blank[ ] 记录两门牌号之间的距离,然后 用数组 an

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

hdu4267区间统计

题意:给一些数,有两种操作,一种是在[a,b] 区间内,对(i - a)% k == 0 的加value,另一种操作是询问某个位置的值。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import

hdu4417区间统计

给你一个数列{An},然后有m次查询,每次查询一段区间 [l,r] <= h 的值的个数。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamRead

hdu3333区间统计

题目大意:求一个区间内不重复数字的和,例如1 1 1 3,区间[1,4]的和为4。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;

POJ2010 贪心优先队列

c头牛,需要选n头(奇数);学校总共有f的资金, 每头牛分数score和学费cost,问合法招生方案中,中间分数(即排名第(n+1)/2)最高的是多少。 n头牛按照先score后cost从小到大排序; 枚举中间score的牛,  预处理左边与右边的最小花费和。 预处理直接优先队列贪心 public class Main {public static voi

ural 1820. Ural Steaks 贪心

1820. Ural Steaks Time limit: 0.5 second Memory limit: 64 MB After the personal contest, happy but hungry programmers dropped into the restaurant “Ural Steaks” and ordered  n specialty steaks