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
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/whenc/p/13854333.html