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;
}
### C++ 实现贪心算法解决杂技表演问题 对于给定的奶杂技问题,目标是在满足条件的情况下使尽可能多的奶参与表演。此问题可以通过贪心策略来求解。 #### 输入处理 程序首先读取输入数据,包括奶的数量`N`及其各自的重量和强壮度。为了简化后续计算,可以定义结构体存储每只奶的信息并将其存入数组中以便操作: ```cpp struct Cow { int weight; int strength; }; Cow cows[20001]; ``` 接着初始化变量用于记录当前累积的压力总和以及已经加入队伍中的成员数目: ```cpp long long totalPressure = 0LL, count = 0LL; ``` #### 数据预处理 考虑到排序后的序列有助于找到局部最优解从而构建全局最优方案,在正式进入循环之前先按照特定规则对原始列表进行升序排列[^3]: ```cpp sort(cows + 1, cows + n + 1, [](const Cow &a, const Cow &b){ return a.weight + b.strength < b.weight + a.strength; }); ``` 这里采用的是比较函数`(weight + strength)`从小到大排序的方式,因为这样能保证较早被选中的个体不会给后来者带来过多额外负担。 #### 主逻辑流程 遍历已排序好的队列,逐个评估能否接纳新的参与者直到无法继续为止。每当成功添加一头新时更新累加器,并增加计数器;一旦发现违反约束则立即停止迭代过程输出结果: ```cpp for (int i = 1; i <= n && totalPressure + cows[i].weight <= cows[i].strength; ++i) { totalPressure += cows[i].weight; ++count; } cout << count << endl; ``` 上述代码片段实现了完整的解决方案框架,通过合理安排顺序使得最终形成的堆叠最为稳固可靠。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chp的博客

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

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

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

打赏作者

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

抵扣说明:

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

余额充值