贪心问题

Posted w-w-t

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贪心问题相关的知识,希望对你有一定的参考价值。

1.POJ-1328 Radar Installation

题意:给出一定数量的岛屿和雷达的观测范围d,问在海岸线最少建设多少个雷达就能覆盖完所有的岛屿。

题目分析:

要想使雷达最少,每个雷达就要尽可能多的覆盖岛屿。我最开始的思路一直是从最左边未被覆盖的岛屿的x坐标开始,
在[x,x+sqrt(d^2 - y^2)]之间选择覆盖最多的x坐标建立一个雷达,并消去被覆盖的岛屿,复杂度太高,而且感觉像模拟,没有抓住贪心题的精髓。

新思路:

可以转换一下对象,原来一直是找最优的点建立雷达,都是对雷达考虑的。现在对岛屿考虑。我们可以将雷达能覆盖到这个岛屿的左右范围求出来,
并对范围进行排序,从左到右,拥有交集范围的一堆岛屿就可以用一个雷达监测。问题就变成了有几堆这样的岛屿(拥有一个公共交点)

解:
求出各岛屿的左右l,r,排序,从左开始,如果某一个岛屿比前面的某个岛屿的right大(Min_r记录前面同一堆岛屿的右侧最小值),说明什么,
说明这个点与前面一堆没有了同一个交点(因为与至少1个岛屿的范围不重合)
否则:更新Min_r值( 代码中是tx )

注意
某岛屿y>d,输出-1
d<=0 输出-1
输出格式
取double

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int MA=1e5+5;
struct node{
	double x;
	double y;
	double l;
	double r;
}a[MA];
bool cmp(struct node z1,struct node z2){
	if(z1.l==z2.l)return z1.r<z2.r;
	else return z1.l<z2.l;
}
int main(){
	int n,d;
	bool flag;
	int t=1;
	while(scanf("%d %d",&n,&d)){
		if(n==0&&d==0)break;
		flag=true;
		if(d<=0)flag=false;
		for(int i=0;i<n;i++){
			scanf("%lf %lf",&a[i].x,&a[i].y);
			if(a[i].y>d)flag=false;
			a[i].l=a[i].x-sqrt(d*d-a[i].y*a[i].y);
			a[i].r=a[i].x+sqrt(d*d-a[i].y*a[i].y);
		}
		sort(a,a+n,cmp);
		int sum=1;
		double tx=a[0].r;
		for(int i=0;i<n;i++){
			if(tx<a[i].l){
				sum++;
				tx=a[i].r;
			}
			else{
				tx=min(a[i].r,tx);
			}
		}
		if(flag)cout<<"Case "<<t<<": "<<sum<<endl;
		else cout<<"Case "<<t<<": -1"<<endl;
		t++;
	}
	return 0;
}

以上是关于贪心问题的主要内容,如果未能解决你的问题,请参考以下文章

763. 划分字母区间-贪心算法

贪心算法----区间覆盖问题(POJ2376)

Contig|scaffold|N50|L50|NG50|贪心算法|de bruiji graph|

CodeForces 1005D Polycarp and Div 3(思维贪心dp)

微信小程序代码片段

hdu2037 今年暑假不AC[贪心][区间调度问题]