耍杂技的牛

题目描述

农民约翰的 N 头奶牛(编号为 1..N)计划逃跑并加入马戏团,为此它们决定练习表演杂技。

奶牛们不是非常有创意,只提出了一个杂技表演:

叠罗汉,表演时,奶牛们站在彼此的身上,形成一个高高的垂直堆叠。

奶牛们正在试图找到自己在这个堆叠中应该所处的位置顺序。

N 头奶牛中的每一头都有着自己的重量 Wi 以及自己的强壮程度 Si

一头牛支撑不住的可能性取决于它头上所有牛的总重量(不包括它自己)减去它的身体强壮程度的值,现在称该数值为风险值,风险值越大,这只牛撑不住的可能性越高。

您的任务是确定奶牛的排序,使得所有奶牛的风险值中的最大值尽可能的小。

输入格式

第一行输入整数 N,表示奶牛数量。

接下来 N 行,每行输入两个整数,表示牛的重量和强壮程度,第 i 行表示第 i 头牛的重量 Wi 以及它的强壮程度 Si

输出格式

输出一个整数,表示最大风险值的最小可能值。

数据范围

1N50000,
1Wi10,000,
1Si1,000,000,000

输入样例:

3
10 3
2 5
3 3

输出样例:

2

算法思路

假设牛按照初始顺序堆叠起来,从上到下编号依次为1、2、3、4.......

不失一般性地取出其中两头牛ii+1,对于这两头相邻的牛,存在以下性质

性质1:如果Wi+1+Si+1<Wi+Si,那么将两头牛更换位置,整个堆叠的最大危险值不会比更换前更大

证明:max(i)max(i+1)

i处危险值 i+1处危险值 最大风险值
交换前 W1+W2+...+Wi1Si W1+W2+...+WiSi+1 max(I)
交换后 W1+W2+...+Wi1Si+1 W1+W2+...+Wi1+Wi+1Si max(I+1)

证明步骤

1、对比交换前i+1处危险值和交换后i处危险值,可知交换前的比交换后的多一个Wi,由题知:Wi1,所以可得ii+1

2、再对比交换前i+1处危险值和交换后i+1处危险值,可知两者差异为WiSi+1Wi+1Si,又由前提知Wi+1+Si+1<Wi+Si,交换可得Wi+1Si<WiSi+1,所以可知i+1i+1

3、又因为i+1max(i),且max(i+1)=ii+1,因此max(i+1)max(i)

得证

又因为假如存在一个最优解不满足Wi+1+Si+1>Wi+Si性质,那么根据性质1,必然可以对其进行调节交换,使其形成的堆叠最终满足这个性质,而且最大危险值不会变大

有了这个性质,我们就可以根据Wi+Si的值,对整个堆叠进行排序,最终按照这个值从小到大排成堆叠就是一个最优解

代码实现

#include<iostream>
#include<algorithm>

using namespace std;
typedef pair<int, int> PII;

const int N = 5e4 + 10;

PII a[N];
int n;

int main(){
    cin >> n;
    for(int x = 0; x < n; x++){
        int w, s;
        cin >> w >> s;
        a[x] = {w + s, w};
    }
    sort(a, a + n);
    int ans = -1e9, weight = 0;
    for(int x = 0; x < n; x++){
        auto c = a[x];
        ans = max(ans, weight - c.first + c.second);
        weight += c.second;
    }
    cout << ans;
}
posted @   INnoVation-V2  阅读(47)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 易语言 —— 开山篇
历史上的今天:
2018-04-18 红黑树
点击右上角即可分享
微信分享提示