POJ 3069 簡單的貪心

題意:給出一些點和這些點能延伸的距離,標記最少的點使得所有的點都可以被標記到(一個點能左右延伸到另一個點,則另一個點視爲被標記)。

分析:走彎路了。。。直接貪心用循環從最做邊開始走就行了。。。結果。。我一開始不知怎麼着想錯了。。。用的二分查找加減之後的最大值。。。。結果一直時間超限。。看了書之後突然意識到。。直接循環就行啊。這樣也就從最左邊到最右邊。時間複雜度僅僅是o(n)。

AC代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxed=1000+10;
int p[maxed],n,r;
int main()
{
    while(scanf("%d%d",&r,&n)!=EOF){
        if(n==-1&&r==-1)
            break;
        for(int i=0;i<n;i++)
            scanf("%d",&p[i]);
        sort(p,p+n);
        int i=0,ans=0;
        while(i<n){
            int x=p[i++];
            while(i<n&&p[i]<=x+r)
                i++;
            if(i<n&&p[i]!=x+r)
                i--;
            x=p[i];
            while(i<n&&p[i]<=x+r)
                i++;
            if(i<n&&p[i]==x+r)
                i++;
            ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}

最後再把自己腦殘的二分代碼放上吧。。引以爲戒。:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxed=1000+10;
int p[maxed],n,r;
int main()
{
    while(scanf("%d%d",&r,&n)!=EOF){
        if(n==-1&&r==-1)
            break;
        for(int i=0;i<n;i++)
            scanf("%d",&p[i]);
        sort(p,p+n);
        int wa=0,ans=0;
        while(true){
            if(wa>n-1)
                break;
            int x=p[wa]+r;
            if(x>=p[n-1]){
                ans++;
                break;
            }
            int a=lower_bound(p,p+n,x)-p;
            if(p[a]!=x)
                a-=1;
            wa=lower_bound(p,p+n,p[a]+r)-p;
            if(p[wa]==p[a]+r)
                wa+=1;
            ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章