题目链接:http://poj.org/problem?id=1328
分析:对于这个题目网络上有很多的博客讲的很好,我就不再重复讲了,依旧是【区间选点问题】;
我想说的是编程的思维问题:我们拿到一个新题,绞尽脑汁的去想如何解决。我们在思考的过程中一定要明确哪些点是我们在大脑中假设的,哪些点是我们惯性思维或者就认为是这样的,其实这些都是思维的不严谨。
就像这个题,我先给出代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=1000+10;
int n,d;
struct node
{
int x,y;
double star,ende;
int f;
} pre[maxn];
bool cmd(node a,node d)
{
return a.star<d.star;
}
double pos=(double)0x3f3f3f3f;
int ans;
int main()
{
int a=1;
int f;
while(~scanf("%d%d",&n,&d)&&n&&d)
{
pos=0x3f3f3f3f;
ans=0;
f=0;
for(int i=0; i<n; i++)
{
cin>>pre[i].x>>pre[i].y;
if(pre[i].y>d) f=1;
pre[i].star=(double)pre[i].x-sqrt(d*d-pre[i].y*pre[i].y);
pre[i].ende=(double)pre[i].x+sqrt(d*d-pre[i].y*pre[i].y);
}
if(f){printf("Case %d: -1\n",a++);continue;}
sort(pre,pre+n,cmd);
pos=pre[0].ende;
ans++;
for(int i=1; i<n; i++)
{
if(pre[i].star>pos)
{
pos=pre[i].ende;
ans++;
}
else pos=min(pos,pre[i].ende);
}
printf("Case %d: %d\n",a++,ans);
}
return 0;
}
我们首先会对所有的区间按左端点从小到大排列,然后通过比较此时的点的左端点和最后选择的雷达点的位置关系就可以求出,倘若pre[i].star>pos 则 pos=pre[i].ende; ans++;做更新操作。
到这关键的来了。
我们通常不会去考虑else pos=min(pos,pre[i].ende); 直接向下循环。要不考虑,是因为我们大脑里先入为主的认为,所有的情况都是这样的:
区间与区间之间只有那样的情况,而不会出现这样的情况:
在这个图中,显然光有if()后的判断是不够的,还需要else pos=min(pos,pre[i].ende); 把pos的位置往回拉一拉。
所以这样一个题,能反映出我们思维的漏洞。问一问自己,自己有哪些假设是可能不成立的呢?