zoukankan      html  css  js  c++  java
  • Cow Acrobats(贪心)

    原题链接

    贪心题做了还没几道,而且之前做的几道也是线段覆盖问题。

    看到这道题还以为是按照体重或者强壮值来排序,但是发现自己太年轻了,刚开始做的时候就觉着不会简单,而且我还只考虑了最下面的一头牛,连题意都没看懂。正解应该是按照体重和强壮值的和进行排序,证明如下:

    设a在上b在下,两头牛的体重和强壮值分别为Wa, Sa, Wb, Sb。

    既然没能力证真,那就先假设最优解然后证伪。

    设a上面所有牛的体重和是sum,因为任意两头相邻的牛交换只会对它俩造成影响,所以不需要考虑其他牛是否会被影响。

    交换前:牛a:sum - Sa

                 牛b:sum + Wa - Sb

    交换后:牛a':sum + Wb - Sa

             牛b':sum - Sb

    由于交换前已经是最优解,那么交换后的最大值必定大于交换前的最大值,也就是max(a, b) < max(a', b'),接着会发现牛b' < 牛b,假设牛b'最大,也就是牛b' < max(牛a, 牛b),即,交换后b不是最大的,所以交换后的a是最大的,且a' > max(a, b)。

    也就是:sum + Sb - Sa > sum - Sa

                  sum + Wb - Sa > sum + Wa - Sb

    化简后:Wb + Sb > Wa + Sa

    这对任意两头相邻的牛都是成立的。

    所以应该按照W和S的和来进行从大到小的排序,即大的在下面,小的在上面。

    代码如下:

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <string>
     4 using namespace std;
     5 
     6 typedef long long LL;
     7 const int N = 50010;
     8 int w[N], s[N];
     9 struct Node{
    10     int w, s;
    11     LL w_s;
    12 }node[N];
    13 
    14 //按照体重从大往小排序
    15 bool cmp(Node a, Node b){
    16     return a.w_s >= b.w_s;
    17 }
    18 LL sum = 0;
    19 int main(){
    20     int n;
    21     cin >> n;
    22     for(int i = 0; i < n; i ++){
    23         cin >> node[i].w >> node[i].s;
    24         node[i].w_s = node[i].w + node[i].s;
    25     }
    26     sort(node, node + n, cmp);
    27     for(int i = 0; i < n; i ++)
    28         sum += node[i].w;
    29     LL maxn = -0x3f3f3f3f;
    30     for(int i = 0; i < n; i ++){
    31         sum -= node[i].w;
    32         maxn = max(maxn, sum - node[i].s);
    33     }
    34     cout << maxn << endl;
    35 
    36     return 0;
    37 }
  • 相关阅读:
    梅特卡夫法则(Metcalfe's law)
    jffs2reset 实现分析
    uhttpd配置文件分析
    疑问????
    ubuntu 修改root密码
    原始套接字
    位操作
    linux命令readlink
    awk 中 FS的用法
    Python做简单爬虫(urllib.request怎么抓取https以及伪装浏览器访问的方法)
  • 原文地址:https://www.cnblogs.com/pureayu/p/13952633.html
Copyright © 2011-2022 走看看