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