poj1328-DP

来源:互联网 发布:在蜂窝数据找不到应用 编辑:程序博客网 时间:2024/05/19 12:40

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

先不说是不是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;}