zoukankan      html  css  js  c++  java
  • Greedy:Protecting the Flowers(POJ 3262)

                  

                        保护花朵

      题目大意:就是农夫有很多头牛在践踏花朵,这些牛每分钟破坏D朵花,农夫需要把这些牛一只一只运回去,这些牛各自离牛棚都有T的路程(有往返,而且往返的时候这只牛不会再破坏花),问怎么运才能使被践踏的花最少?

      一开始我做这道题的时候,用的是贪婪算法,然后我是这样做的,我先把D按照逆序排一遍,然后如果D相等的时候,再按T的顺序排序,然后两两比较看最小,就选谁,自以为是一个非常好的思路,但是果断WA了。

      其实你要问我为什么这个思路?我一开始是这么想的,我想尽量让D大的元素出列,然后让T尽量少影响最后的结果,但是我没有注意到其实这个最小时间不仅仅是由D决定的,是T和D共同决定的成果,比如给一组这样的数据 4 :(2,1),(1,3),(5,7),(4,8),这个算法是选(4,8)(1,3),(5,7),(2,1)来得出最后结果为114,而其实还有更好的结果:先选(1,3),然后(4,8),(5,7),(2,1)结果为106,所以这个结果很明显就是错的

      那么我们应该怎么办呢?我们看到,如果我们单独选择两个牛的时候,其实选完这两头牛,对后面是没有影响的(时间均为t1+t2),那么在这两头牛之间选择,所以其实我们只要看2*ta*DB和2*tb和DA之间的大小关系就可以了(DB+DA=SAB,所以在SAB里面而TA刚好就是对应DB,反之同理),进而我们只用看TA/DA和TB/DB的关系就可以了!!!这个区间思想拓展到整个区间就是我们要的算法我们按照TX/DX排顺序,最后出来的结果就是答案

      

     1 #include <iostream>
     2 #include <functional>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 typedef struct set_
     8 {
     9     int T;
    10     int D;
    11 }Cows;
    12 
    13 void Search(const int,const int);
    14 
    15 int fcmop(const void *a, const void *b)
    16 {
    17     return (double)((*(Cows *)a).T) / (double)((*(Cows *)a).D) >
    18         (double)((*(Cows *)b).T) / (double)((*(Cows *)b).D) ? 1 : -1;
    19 }
    20 static Cows Cows_Set[100000];
    21 
    22 int main(void)
    23 {
    24     int Cows_sum, sum_D;
    25 
    26     while (~scanf("%d", &Cows_sum))
    27     {
    28         sum_D = 0;
    29         for (int i = 0; i < Cows_sum; i++)
    30         {
    31             scanf("%d%d", &Cows_Set[i].T, &Cows_Set[i].D);
    32             sum_D += Cows_Set[i].D;
    33         }
    34         /*为什么可以按照ea/排序?
    35          *非常简单,因为当我们以两头牛两头牛选择的时候,我们会发现其实我们选完这两头牛的时候,后面的牛根本不受影响
    36          *所以我们只要不断取2*ea*tb<2*eb*ta最小即可
    37         */
    38         qsort(Cows_Set, Cows_sum, sizeof(Cows), fcmop);
    39         Search(Cows_sum, sum_D);
    40     }
    41     return 0;
    42 }
    43 
    44 void Search(const int Cows_sum, const int sum_D)
    45 {
    46     long long lastA, j, sum_last = sum_D,ans = 0;
    47 
    48     for (j = 0; j < Cows_sum; j++)
    49     {
    50         sum_last-= Cows_Set[j].D;
    51         ans += sum_last * 2 * Cows_Set[j].T;
    52     }
    53     printf("%lld
    ", ans);
    54 }

  • 相关阅读:
    django 在保存数据前进行数据校验
    itertools
    python 发送请求
    python 异常处理
    python 对redis 键值对的操作
    python 对redis key的基本操作
    python 操作redis数据
    一只青蛙一次可以跳1阶或者2阶,n阶,有多少种到达终点的方式。
    Django 自定义扩展命令
    关于函数可变参数
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/4898952.html
Copyright © 2011-2022 走看看