AcWing 125. 耍杂技的牛

算法1

(贪心)

题目要求牛的最大伤害值最小,那么我们使每头牛的伤害值最小,在其中找最大值作为答案

如何使得每头牛的伤害值最小?

(1) 自身w值越大应该放到底部,使得被减数减小

(2) 自身s值越大应该放到底部,使得减数变大

综上,w + s 从小到大排序,最大的危险系数一定是最小的。

贪心算法的证明过程:

贪心所得到的解 == 最优解

(1)贪心所得到的解 >= 最优解

由于最终答案所有可行方案中的最大值,而用贪心得到的解是一个可行解,因此最优解一定大于贪心得到的解

(2)贪心得到的解 <= 最优解

假设最优解不是 w + s从小到达排序的,那么必然存在相邻两头牛,使得 $w_i$ + $s_i$ > $w_i+1$ + $si+1$

交换前的伤害值:

第i个位置上的牛:$ w_1 + w_2 + ... + w_~i-1 - s_i $

第i+1个位置上的牛:$ w_1 + w_2 + ... + w_i-1 + w_i - s_~ i + 1$

交换后的伤害值:

第i个位置上的牛:$ w_1 + w_2 + ... + w_~i-1 - s_~i+1 $

第i+1个位置上的牛:$ w_1 + w_2 + ... + w_~i-1 + w_i+1 - s_i$

由于交换前和交换后的式子当中都有$w_1 + w_2 + ... + w_i-1$,因此我们可以同时去掉他

再加上$s_i + s_i+1$

去掉w[1] + ...+w[i-1]之后:

         第i个位置上的牛      第i+1个位置上的牛
         
交换前: -s[i]                w[i] - s[i + 1]

交换后: -s[i + 1]            w[i+1] - s[i]

----------
加上(s[i] + s[i+1])之后:

         第i个位置上的牛     第i+1个位置上的牛
         
交换前: s[i+1]               w[i]+s[i]

交换后: s[i]                 w[i+1]+s[i+1]

从上面的式子当中可以看出,$w_i + s_i > s_i$

又我们再前面假设当中 $w_i$ + $s_i$ > $w_i+1$ + $si+1$

因此,我们可以得出 (交换前)$s_i+1 + w_i + s_i $ 大于(交换后) $s_i + w_i+1 + s_i+1$

也就是说,交换后的值,严格变小了, 此时我们可以证明出贪心得到的值 <= 最优值

证毕!

C++ 代码

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

typedef pair<int,int>PII;
const int N = 50010;

int n;
PII cow[N];

int main(){
    scanf("%d",&n);
    for(int i = 0 ; i < n; i++){
        int w,s;
        scanf("%d%d",&w,&s);
        cow[i] = {w + s, w};   
    }
    
    //按照 w + s 从小到大进行排序
    sort(cow, cow + n);
    
    int ans = -2e9, sum = 0;   //sum表示当前我头上的牛的重量
    for(int i = 0; i < n; i ++){
        int w = cow[i].second, s = cow[i].first - w;  //当前牛的强壮值
        ans = max(ans, sum - s); //我头上的牛的总重量 - 我的强壮值
        sum += w;
    }
    printf("%d",ans);
    return 0;
}

posted @ 2024-09-18 22:07  LTphy  阅读(36)  评论(0)    收藏  举报