• Codeforces Round #182 (Div. 1) B. Yaroslav and Time(二分+SPFA变形)


    题目大意

    有 n(3n100) 个站点,当第一次到达站点 u 的时候会增加寿命 au(1≤au≤103),题目给了 n 个站点的二位空间坐标,每两个站点之间的距离为曼哈顿距离(dis(i, j)=|xi-xj|+|yi-yj|),从站点 i 到达站点 j 需要的时间为 dis(i, j)*d(d 是题目给定的一个常数,且 103≤d≤105)。某个人最开始的时候在站点 1,他想到站点 n 去,问,他最开始至少剩下多少寿命才能活着到达站点 n?

    做法分析

    很容易想到二分寿命值,但是怎么判断在某个具体的寿命下,能否到达第 n 个站点呢?

    注意题目给的数据范围:1≤au≤103 且 103≤d≤105

    想到了什么?

    对了,如果直接用 SPFA 跑一遍最长路,是不会在路径上出现重复节点的!如果出现重复节点就会形成一个负环,这样肯定不如前面的优!因为就算每到一个节点都增加以下寿命,由于寿命增加的肯定比在路上消耗的小,所以寿命是随着经过的节点的数量而递减的!

    那么,每当遇见 f[u]-dis(i, u)*d+A[i]>f[i] (其中:f[u] 表示到达 u 节点剩余的最大寿命值,A[i] 表示第一次进入 i 节点增加的寿命值)的时候,肯定是从另一条路径到达的 i 节点。那么,我跑一遍 SPFA,看能不能到达 n 节点,这样,就判断出来了

    参考代码

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <cstdio>
     5 #include <queue>
     6 
     7 using namespace std;
     8 
     9 typedef long long LL;
    10 const int N=106;
    11 
    12 LL d, A[N], f[N];
    13 bool vs[N];
    14 int X[N], Y[N], n;
    15 queue <int> q;
    16 
    17 inline LL dis(int a, int b)
    18 {
    19     return abs(X[a]-X[b])+abs(Y[a]-Y[b]);
    20 }
    21 
    22 bool judge(LL init)
    23 {
    24     memset(f, -1, sizeof f);
    25     while(!q.empty()) q.pop();
    26     memset(vs, 0, sizeof vs);
    27     q.push(1), f[1]=init, vs[1]=1;
    28     while(!q.empty())
    29     {
    30         int u=q.front();
    31         q.pop(), vs[u]=0;
    32         for(int i=1; i<=n; i++)
    33         {
    34             if(dis(i, u)*d>f[u] || i==u) continue;
    35             if(f[u]-dis(i, u)*d+A[i]>f[i])
    36             {
    37                 f[i]=f[u]-dis(i, u)*d+A[i];
    38                 if(!vs[i]) q.push(i), vs[i]=1;
    39             }
    40         }
    41     }
    42     if(f[n]==-1) return false;
    43     return true;
    44 }
    45 
    46 int main()
    47 {
    48     scanf("%d%I64d", &n, &d);
    49     for(int i=2; i<n; i++) scanf("%I64d", &A[i]);
    50     for(int i=1; i<=n; i++) scanf("%d%d", &X[i], &Y[i]);
    51     LL L=0, R=((1LL)<<60);
    52     while(L<R)
    53     {
    54         LL mid=(L+R)>>1;
    55         if(judge(mid)) R=mid;
    56         else L=mid+1;
    57     }
    58     if(!judge(L)) L++;
    59     printf("%I64d\n", L);
    60     return 0;
    61 }
    B. Yaroslav and Time

    题目链接 & AC通道

    Codeforces Round #182 (Div. 1) B. Yaroslav and Time

  • 相关阅读:
    css3动画栈效果_1
    页面滚动时出现固定导航
    jquery定位到指定元素
    seajs之学习2
    seajs之学习1
    变态ie6之要求css与页面编码一致引发的问题
    ASP.NET学习笔记一
    C++学习笔记三(类和对象)
    C++学习笔记二
    unity3D学习笔记一
  • 原文地址:https://www.cnblogs.com/zhj5chengfeng/p/3082427.html
Copyright © 2020-2023  润新知