现在的位置: 首页 > 综合 > 正文

poj1328-DP

2012年10月05日 ⁄ 综合 ⁄ 共 1147字 ⁄ 字号 评论关闭

没想到这是道水题,我先把意思搞错了,认为雷达是建立在小岛中,个岛相互联系,我就有点摸不着思路,无赖之下,到网上一搜,我才知道,自己想错了。这完全是数学分析题,

先不说是不是DP,我们先要对问题进行模型化,即数学建模,既然是建在海岸线边,问题就简化了许多。简化为区间覆。,要使一个岛屿被圆覆盖,最极端的情况,就是刚好在圆周边上,

这是一个处理问题的一个关键点,想想看,要减少雷达的个数,我们就必定把每个雷达的范围尽量拉开。这就是DP思想,DP思路就是,把大问题转换为单个子问题,如果我每一步,都尽量使得雷达在x轴的范围大一些,最终,要覆盖整个岛,使用的就一定少一些,这难道不是贪心吗?

知道这个,还一个值得注意的地方就,对情况的分类,我们先求出每个岛在雷达的覆盖下,在x轴的最大范围(区间)求出来,再从x轴的最左边的 岛屿开始。第一种情况:

当该岛屿x1右边的值大于另一个岛屿x2右边(那么它一定大于x2左边的值,因为x2左边<x2右边),画个图,就知道了,它正好是第二个岛包含了第一个岛屿,刚好与区间覆盖相反,别搞错了。那么,就不必要再建。还有这种情况,就是不包含,即最右边的点小于第二个岛屿最左的点,那就必须建了。理解了这两种情况。再把在最右边的点,赋值给一个递归变量的保存者,一次传递下去,就行了。

代码如下:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
struct node{
	double l,r;
}reda[1000];

bool cmp(node a,node b)
{
	return a.l<b.l;
}
int main()
{   
	int n,c=0;
	double len,r,d,x,y;	
	while(scanf("%d%lf",&n,&d)!=EOF)
	{    
		int flag=1;
		if(!n&&!d) break;
		for(int i=0;i<n;i++)
		{
		   scanf("%lf%lf",&x,&y);
			if(d>=y&&flag)
			{
			r=sqrt(d*d-y*y);
			reda[i].l=x-r;
			reda[i].r=x+r;
	     	}
	     	else
	     	 flag=0;
		}
		if(!flag) printf("Case %d: -1\n",++c);
		else
		{
			sort(reda,reda+n,cmp);
			int ans=1;
			len=reda[0].r;        //初始化递归变量的保存者。 
			for(int i=1;i<n;i++)
			{
			 if(len<reda[i].l){     //看分析,就理解了。 
				ans++;
				len=reda[i].r;
			  }
			else if(len>=reda[i].r){
				len=reda[i].r;
			 }		
		    } 
		 printf("Case %d: %d\n",++c,ans);
		}
	}
	 return 0;
}
			
			
			

抱歉!评论已关闭.