【每日算法】基础算法——耍杂技的牛(九十二)

题目内容

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

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

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

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

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

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

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

输入格式

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

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

输出格式

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

数据范围

1≤N≤50000 ,
1≤$W_i$≤10,000,
1≤$S_i$≤1,000,000,000

输入样例

3
10 3
2 5
3 3

输出样例

2

题解

根据题,我们可以有如下思考:
交换前 交换后
第i头牛 $W1$+…+$W{i-1}$-$Si$ $W_1$+…+$W{i-1}$+$W{i+1}$-$S_i$
第i+1头牛 $W_1$+…+$W
{i}$-$S{i+1}$ $W_1$+…+$W{i-1}$-$S_{i+1}$

为了比较大小关系,把公共部分去掉得到
交换前 交换后
第i头牛 -$Si$ $W{i+1}$-$Si$
第i+1头牛 $W
{i}$-$S{i+1}$ -$S{i+1}$

要比较的是交换前的两行数值和交换后的两行数值的值,分析如下:
当$Wi$+$S_i$ > $W{i+1}$+$S_{i+1}$时,交换后危险系数会降低。

代码

#include <iostream>
#include <algorithm>
#include <limits.h>

using namespace std;

typedef pair<int,int> PII;

const int N = 50010;

int n;
PII cows[N];

int main(){
cin >> n;
for(int i = 0; i < n; i++){
int w,s;
cin >> w >> s;
cows[i] = {w+s,w};
}

sort(cows,cows+n);
int sum = 0,res = INT_MIN;
for(int i = 0;i<n;i++){
int w = cows[i].second,s = cows[i].first - w;
res = max(res,sum-s);
sum+=w;
}

cout << res <<endl;
return 0;
}
Author: Frederic Niu
Link: https://www.fredericniu.cn/2021/03/02/【每日算法】基础算法——耍杂技的牛(九十二)/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
我的公众号