【 贪心 进阶总结 】【 来自一本通提高篇 】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/violinlove/article/details/82814874

#10000. 「一本通 1.1 例 1」活动安排

区间与区间的最大不覆盖数—套板子(区间右端点从小到大排序,选择不冲突的,尽可能的选)简记为线段覆盖问题

#10001. 「一本通 1.1 例 2」种树

区间内最少单点满足覆盖要求,不管是各个区间需要一个点还是一个子区间(这个子区间是可连续、可不连续的)

按照区间右端点从小到大排序,依次满足各个区间的要求,如此下来种的树(需要的点)最少。

如果想不出贪心,线段树+优化亦可作。

#10002. 「一本通 1.1 例 3」喷水装置

选择尽量少的区间覆盖指定线段区间。

【 模板 】将所有的区间按照左端点从小到大排序,对于当前查找的起点s ,选择覆盖点 s 的区间中右端点中最大的一个,并将 s 更新为此区间的右端点,(这样区间数目+1)直到s>=整个线段长度。(在s时刻,找一个左端点小于等于s的最大右端点)

对于这道题,需要进行一些转化——每个浇灌喷头受限于所能喷到的最短距离,它的最短距离是半径到达草坪上端。此时,如果将整个草坪长度想象为 x轴的正半轴,那么,我们应该根据勾股定理找到水平距离,即(\sqrt{r^{2}-(\frac{W}{2})^{2}})。把当前点的pos减去水平距离作为左端点,pos+水平距离作为右端点。然后就是套上面的板子↑。

PS:一定要理解了过程再写,一定要理解了过程再写,一定要理解了过程再写!!!

附上AC代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define N 300005

using namespace std;

const double Eps = 1e-5 ;

inline int wread(){
    char c=getchar ();int flag=1,wans=0;
    while (c<'0'||c>'9'){if (c=='-') flag=-1;c=getchar ();}
    while (c>='0'&&c<='9'){wans=wans*10+c-'0';c=getchar ();}
    return wans*=flag;
}

int T;
int n,L,W;
struct node {double lx,rx;int pos,r;}a[N];
bool e666 (node x,node y){return x.lx<y.lx;}

int main (){
	T=wread();
	while (T--){
		memset (a,0,sizeof a);
		n=wread();L=wread();W=wread();
		for (int i=1;i<=n;++i){
			a[i].pos=wread(),a[i].r=wread();
			if (a[i].r*a[i].r-(W*1.0/2.0)*(W*1.0/2.0)<0)	a[i].pos=-1,a[i].lx=-1,a[i].rx=-1;
			//对于不能覆盖完草坪上端的一个圆(例如样例1中的那个夹在草坪中间的圆) 肯定是不会选它的 
			else {
				a[i].lx=max (0.000000,(double)a[i].pos-sqrt((double)a[i].r*(double)a[i].r-(W*1.0/2.0)*(W*1.0/2.0)));
				a[i].rx=a[i].pos+sqrt((double)a[i].r*(double)a[i].r-(W*1.0/2.0)*(W*1.0/2.0));					
			}
		}

		sort (a+1,a+n+1,e666);	
		
		int nx=1; 
		double s=0;//起点 
		bool F=true;//判断是否能覆盖完整个区间 
		int ans=0;//记录 
		
		while (nx<=n){
			ans++;
			double re=s;
			while (a[nx].lx<=re && nx<=n){//模板 
				if (a[nx].rx>=re)	s=max(s,a[nx].rx);
				nx++;
			}
			if (s>=L)	{break;}
			if (re==s)	{F=false;break;}//未更新,请画图____即当前区间与下个区间之间 一定有一段距离,不符合全部覆盖的要求,退出 
		}
		if (!F)	puts("-1");
		else	printf("%d\n",ans);
	}
	return 0;
}

未完待续...

猜你喜欢

转载自blog.csdn.net/violinlove/article/details/82814874