CodeForces 545C - Woodcutters(贪心)

题目链接 https://cn.vjudge.net/problem/CodeForces-545C

【题意】
无限长的数轴上有n个点,每个点的坐标为x[i],种有高度为h[i]的树,现在要把一些树砍到,被砍倒的树要么倒向左边,要么倒向右边,会分别把[xi - hi, xi] 和 [xi,xi + hi]占用,如果某棵树不被砍倒,那么它就只占用x[i]这一个点的位置,现在给定你n个点的x[i],h[i],问最多能砍倒几棵树?(n<=1e5, x[i],h[i]<=1e9)

【思路】
贪心问题,很关键的地方在于对于某个区间[xi,x(i+1)]来说,这段区间要么被xi利用,要么被x(i+1)利用,要么被它们两个都利用,要么都不用,只有这四种可能。所以n个点把数轴划成了n+1个区间,我们从左往右依次枚举这n+1个区间即可,尽可能地让这些区间占用更多的树即可

#include<bits/stdc++.h>
using namespace std;

const int inf=2e9;
const int maxn=100050;

int n;
bool used[maxn];
struct node{
    int x,h;
    bool operator<(const node& e)const{
        return x<e.x;
    }
}tree[maxn];

int main(){
    scanf("%d",&n);
    for(int i=0;i<n;++i){
        scanf("%d%d",&tree[i].x,&tree[i].h);
    }
    sort(tree,tree+n);
    int ans=0;
    for(int i=0;i<=n;++i){//枚举n+1段路
        if(0==i){//最左边的路放tree[0]
            used[0]=1;
            ++ans;
            continue;
        }
        if(n==i && !used[n-1]){//如果最右边的树没着落,那就放到最右边的路上
            used[n-1]=1;
            ++ans;
            continue;
        }

        int le= tree[i-1].x;
        int ri= tree[i].x;

        if(used[i-1]){//左边的树已经搞定了,只考虑当前的树就可以,能放就放
            int len=ri-le;
            if(len>=tree[i].h+1) { used[i]=1; ++ans; }
        }
        else{//左边的树还没着落,能都放下就都放下,放不下优先考虑放左边的
            int len=ri-le+1;
            if(len>=tree[i-1].h+1 + tree[i].h+1){
                used[i-1]=used[i]=1;
                ans+=2;
            }
            else if(ri-le>=tree[i-1].h+1){
                used[i-1]=1;
                ++ans;
            }
            else if(ri-le>=tree[i].h+1){
                used[i]=1;
                ++ans;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}
posted @ 2018-04-14 13:43  不想吃WA的咸鱼  阅读(120)  评论(0编辑  收藏  举报