AcWing125. 耍杂技的牛(贪心+推公式)

题目链接AcWing125. 耍杂技的牛
在这里插入图片描述

分析:
这是一道贪心问题,我们假设牛最终的摆放顺序(从上大小)为1,2,3,...i,i+1,...,n,当存在相邻的两头牛i,i+1如果 w i + s i > w i + 1 + s j + 1 w_i+s_i> w_{i+1}+s_{j+1} wi+si>wi+1+sj+1 那么交换两头牛i,i+1的位置,后所有牛风险值的最大值不会变大。
证明:
首先,可以容易想到交换两头牛i,i+1的位置不会对1~i-1i+1~n牛的风险值产生影响
我们将1~i-1头牛的重量表示为 w 上 w_{上} w
那么,
i头牛的风险值为 w 上 − s i w_{上}-s_i wsi
i+1头牛的风险值为 w 上 + w i − s i + 1 w_{上}+w_i-s_{i+1} w+wisi+1
此时,两头牛i,i+1的最大风险值为 max ⁡ ( w 上 − s i , w 上 + w i − s i + 1 ) \max(w_{上}-s_i,w_{上}+w_i-s_{i+1}) max(wsi,w+wisi+1)
交换两头牛i,i+1的位置后
i头牛的风险值为 w 上 − s i + 1 w_{上}-s_{i+1} wsi+1
i+1头牛的风险值为 w 上 + w i + 1 − s i w_{上}+w_{i+1}-s_{i} w+wi+1si
此时,两头牛i,i+1的最大风险值为 max ⁡ ( w 上 − s i + 1 , w 上 + w i + 1 − s i ) \max(w_{上}-s_{i+1},w_{上}+w_{i+1}-s_{i}) max(wsi+1,w+wi+1si)
因为 w i + s i ≥ w i + 1 + s j + 1 w_i+s_i\geq w_{i+1}+s_{j+1} wi+siwi+1+sj+1 ,所以有 w i − s i + 1 ≥ w i + 1 − s j i w_i-s_{i+1}\geq w_{i+1}-s_{ji} wisi+1wi+1sji
所以有:
w 上 + w i − s i + 1 > w 上 + w i + 1 − s i w_{上}+w_i-s_{i+1}>w_{上}+w_{i+1}-s_{i} w+wisi+1>w+wi+1si
w 上 + w i + 1 − s i > w 上 − s i w_{上}+w_{i+1}-s_{i}>w_{上}-s_i w+wi+1si>wsi
w 上 + w i − s i + 1 > w 上 − s i + 1 w_{上}+w_i-s_{i+1}>w_{上}-s_{i+1} w+wisi+1>wsi+1
所以有 max ⁡ ( w 上 − s i , w 上 + w i − s i + 1 ) > max ⁡ ( w 上 − s i + 1 , w 上 + w i + 1 − s i ) \max(w_{上}-s_i,w_{上}+w_i-s_{i+1})>\max(w_{上}-s_{i+1},w_{上}+w_{i+1}-s_{i}) max(wsi,w+wisi+1)>max(wsi+1,w+wi+1si)
所以,存在相邻的两头牛i,i+1如果 w i + s i > w i + 1 + s j + 1 w_i+s_i> w_{i+1}+s_{j+1} wi+si>wi+1+sj+1 那么交换两头牛i,i+1的位置,后所有牛风险值的最大值会变小。
类似于冒泡排序的思路,可以用贪心的思想来找到该问题的一个最优解,就是按照 w i + s i w_i+s_i wi+si从小到大的顺序从高往低摆放牛

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int N=5e4+10;
typedef pair<int,int> pii;
typedef long long ll;
vector<pii> v;

int main(){
    int n;
    int res=-1e9;
    cin>>n;
    for(int i=0;i<n;i++){
        int w,s;
        scanf("%d%d",&w,&s);
        v.push_back({w+s,w});
    }
    sort(v.begin(),v.end());
    ll ans=0;
    for(int i=0;i<v.size();i++){
        if(ans-v[i].first+v[i].second>res) res=ans-v[i].first+v[i].second;

        ans+=v[i].second;
    }
    cout<<res;
    return 0;
}
  • 19
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chp的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值