• 洛谷 P2672 推销员


    题目传送门

    解题思路:

    我们会发现本题有一个特性,就是如果我们走到一个更远的地方,那么近的地方距离原点的距离我们可以忽略.

    本题要求最大的疲劳值,所以我们需要排序,第一个想到堆,反正我是先想到堆.

    然后我们再看题目,因为最后疲劳值是由两部分组成的:路径疲劳值和推销疲劳值.又因为第一行提到的,所以我们可以选一个点k(后面解释),将每个状态下分为两种点:

    1.比当前k点距离原点更近,这些点的疲劳值其实只有推销疲劳值,因为我们已经走得更远了,所以顺道处理这些就行,不需要走多余的路

    2.比当前k点距离原点更远,这些点的疲劳值其实就是推销疲劳值+两倍路径疲劳值-两倍k的路径疲劳值

    而其实最大疲劳值就是这两种点各自的最大值的最大值,所以我们可以用两个大根堆来存,取两个堆顶的较大值即可.

    返回来,k是什么呢?k就是我们当前已经选过的点里最靠右的.

    为什么呢?因为对我们来说只要某个点走了,则这个点左边所有点我们都可以顺路经过,并不需要多余路径疲劳值,所以我们只要记录最右即可.

    代码处理的一些细节:

    1.一开始右边的堆将所有点放进去,左边堆为空,选一个最大点为第一个k.

    2.每当我更新一个k,我再将k左边所有的点推进左边堆.不这么做也可,只是这样代码好写

    3.那么我们更新k后怎么判断右边堆那些在当前k的左边呢?因为k是动态的,所以原来在右边的可能到右边我们只要判断当前元素和k谁到原点近即可,所以我们要不单要记录疲劳值,还要记录路径值,所以我们要定义结构体来构造堆.

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<queue>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 
     8 struct node {
     9     int v, distance,ans;//推销值,距离值,最终值 
    10     node() { }
    11     bool operator < (const node & p) const {
    12         return v + 2 * distance < p.v + 2 * p.distance;//按照疲劳值由大到小排序 
    13     }
    14 }e[100001];
    15 
    16 struct kkk {
    17     int _v,_distance;
    18 }_e[100001];
    19 
    20 priority_queue <node> b;//右边堆 
    21 priority_queue <int> a;//左边堆 
    22 int n,A,vv[100001],k,bj,m,n1;
    23 
    24 bool cmp(kkk aa,kkk bb) {
    25     return aa._distance < bb._distance;
    26 }
    27 
    28 void solve() {//解题过程 
    29     while(n1--) {
    30         if(b.top().ans - 2 * k >= a.top()) {//我忍不住要吐槽,将ans改成v,能得一半分,另一半TLE,这数据太弱了,害得我以为自己代码时间复杂度太高 
    31             if(b.top().distance <= k) {
    32                 b.pop();
    33                 n1++;
    34                 continue;
    35             }
    36             m += b.top().ans - 2 * k;
    37             k = b.top().distance;
    38             b.pop();
    39             for(;bj <= n; bj++) 
    40                 if(_e[bj]._distance >= k)
    41                     break;
    42                 else
    43                     a.push(_e[bj]._v);
    44         }
    45         else {
    46             m += a.top();
    47             a.pop();
    48         }    
    49         printf("%d
    ",m);
    50     }
    51 }
    52 
    53 void firstime() {//第一次处理,之后便与解题思路一致 
    54     m = b.top().ans;
    55     cout << m << endl;
    56     n1 = n;
    57     n1--;
    58     k = b.top().distance;
    59     b.pop();
    60     for(bj = 1;bj <= n; bj++)
    61         if(_e[bj]._distance >= k)
    62             break;
    63         else
    64             a.push(_e[bj]._v);
    65 } 
    66 
    67 int main()
    68 {
    69     scanf("%d",&n);
    70     for(int i = 1;i <= n; i++) {
    71         scanf("%d",&e[i].distance);
    72         _e[i]._distance = e[i].distance;    
    73     }
    74     for(int i = 1;i <= n; i++) {
    75         scanf("%d",&vv[i]);
    76         _e[i]._v = e[i].v = vv[i];
    77         e[i].ans = e[i].v + 2 * e[i].distance;
    78         b.push(e[i]);
    79     }
    80     sort(_e+1,_e+1+n,cmp);//按照距离原点远近排序 
    81     firstime();
    82     solve();
    83     return 0;
    84 }

    //NOIP普及 2015 T4

     

  • 相关阅读:
    windows 安装 anaconda
    全局路径规划--A*算法详解
    编码的种类
    request的encode和decode
    BGP的13条选路原则
    BGP路由黑洞 路由反射器 和联盟2021-07-28
    JMS-ActiveMQ-SpringBoot
    JMS-ActiveMQ-Spring
    JMS-中间件MQ-activeMQ入门
    spring-ssm整合
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/11037364.html
Copyright © 2020-2023  润新知