1. 程式人生 > >poj-1328Radar Installation(貪心)

poj-1328Radar Installation(貪心)

分析:對於這個題目網路上有很多的部落格講的很好,我就不再重複講了,依舊是【區間選點問題】;

我想說的是程式設計的思維問題:我們拿到一個新題,絞盡腦汁的去想如何解決。我們在思考的過程中一定要明確哪些點是我們在大腦中假設的,哪些點是我們慣性思維或者就認為是這樣的,其實這些都是思維的不嚴謹。

就像這個題,我先給出程式碼:

#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的位置往回拉一拉。

所以這樣一個題,能反映出我們思維的漏洞。問一問自己,自己有哪些假設是可能不成立的呢?