算法题解----ACWing 125. 耍杂技的牛

题目描述:

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

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

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

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

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

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

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

输入格式:

 

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

 

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

输出格式:

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

数据范围:

≤ ≤ 50000,

≤ W≤ 10,000

≤ S≤ 1,000,000,000

输入样例:

3

10 3 

2 5

3 3

输出样例:

2

 

思路:

  这题要用到贪心的思想,而Y总评价时说诸多算法中最难的是dp和贪心算法,因为他没有一个固定的模板

 我们如果想要严格解题的话就需要写出严格的证明,推出公式并且证明可行,很多时候显然的结论想要去证明它

   还是不容易的。

  那么这题我先把结论说一下再证明一遍:

  这题我们首先要对每头牛进行排序,排序的规则是:按照 Wi + Si 来排序,然后再从这些牛中找到风险值最大的那头牛。

  下面就是证明:

  

  

 

  

师爷,你来给我翻译翻译他妈的什么叫他妈的惊喜!

 

惊喜就是我们发现我们在序列中如果存在 Wi + Si > Wi+1 + Si+1的逆序对的时候

我们都有唯一的方法去把这个逆序对变成顺序对,反之则不可以

也就是说,我们按照数列的想法这个应该是最后答案的形式

所以这题的排序就一定要以 Wi + Si 的大小来排序。

 

 

话不多说 上代码~

 

# include <iostream>
# include <algorithm>
using namespace std;

 

const int N = 50000+10;

 

struct Cow
{
  int w,s;
  bool operator< (const Cow& c) const    //重载小于号
  {
    return (w+s) < (c.w+c.s);
  }
}cow[N];        //声明这么些牛

 

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

  sort(cow,cow+n);       //对这些牛排序

  int res = -2e9;         //我们的结果,初始化为负无穷
  int sum = 0;            //这是这头牛上面的牛的重量之和
  for(int i=0;i<n;i++)
  {
    res = max(res,sum-cow[i].s);       //答案要找出最小风险值中的最大值
    sum += cow[i].w;              //前面牛的体重要加上去
  }
  cout<<res;
  return 0;
}

 

posted @ 2021-08-20 00:33  Apak陈柏宇  阅读(516)  评论(0编辑  收藏  举报