CF545C Woodcutters(贪心)题解

贪心算法两句话

第一句话:

能往左倒就往左倒。

如同数学中“我们不妨设”一样,相信很好理解。这里只对第二句话稍作解释:

不能往左倒的尽量往右倒

这样为什么是对的呢?

我们可以分类讨论一下:

  • 假设当前已经处理到第\(i\)个,且它不能往左倒,\(h_i\)表示树高,\(x_i\)表示位置。

  • \(x_{i + 1} - x_i > h_i\),也就是说i可以往右倒,那么它有两种选择:

    1. 往右倒。如果倒完以后\(i+1\)还能向左倒,那么显然最优;如果倒完之后\(i+1\)不能往左倒了,

      那么在处理\(i+1\)时会考虑它能否往右,但我们发现\([i-i + 1]\)这段区间内的贡献已达到了最大值(因为就算让\(i + 1\)往左倒这段区间对答案贡献也为\(1\)),因此不会使答案变差。

    2. 不往右倒。假如\(i + 1\)既能往左倒又能往右倒,那么如果\(i\)不往右倒就会影响答案,所以不能选。

  • \(x_{i + 1} - x_i \leq h_i\),也就是说不能往右倒,这时它根本没得选。

综上,我们证明了该贪心算法的正确性,希望这对你有所帮助。

贴一波代码

#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 1e5 + 10;
int n,ans;
struct Tree{
    int h,x;
}t[maxn];

int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i) scanf("%d%d", &t[i].x, &t[i].h);
    ans = 2;
    for(int i = 2; i < n; ++ i){
        if(t[i].x - t[i - 1].x > t[i].h) ans ++;
        else if(t[i + 1].x - t[i].x > t[i].h) ans ++, t[i].x += t[i].h;
    } printf("%d\n", ans);
    return 0;
}
posted @ 2020-10-21 19:58  When_C  阅读(92)  评论(1编辑  收藏  举报