zoukankan      html  css  js  c++  java
  • UVALive

    题目大意:给出出发点和终点和m个虫洞(虫洞的出发点。终点,生成时间和花费时间)。问从起点到终点花费的最小时间

    解题思路:关键是有负环,所以直接跑最短路算法的话会TLE。所以负环要处理一下
    可是这个负环又不是负环。由于负环到一定程度的话。就会消失。
    比方。到达时间小于虫洞的生成时间,那么负环就消失了。也就是说,负环内的点满足的最优情况就是到达时间刚好等于生成时间
    所以,先找出负环,接着推断一下这个负环内的能节省的最多时间。然后将全部点都减去那个时间,那么负环就消失了
    详细看代码

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    
    #define N 110
    #define INF 0x3f3f3f3f
    
    struct Point{
        int x, y, z;
    }s1, s2;
    
    struct wormhole{
        Point s, t;
        int start, cost;
    }W[N];
    
    int n, source, sink;
    int dis[N][N];
    
    int distance(int i, int j) {
        int x = W[i].t.x - W[j].s.x;
        int y = W[i].t.y - W[j].s.y;
        int z = W[i].t.z - W[j].s.z;
        return ceil(sqrt(1.0 * x * x + 1.0 * y * y + 1.0 * z * z));
    }
    
    void init() {
        scanf("%d%d%d%d%d%d%d", &s1.x, &s1.y, &s1.z, &s2.x, &s2.y, &s2.z, &n);
        source = 0;
        sink = n + 1;
        W[0].s = s1;
        W[0].t = s1;
        W[0].start = -INF;
        W[0].cost = 0;
    
        W[sink].s = s2;
        W[sink].t = s2;
        W[sink].start =-INF;
        W[sink].cost = 0;
    
        for (int i = 1; i <= n; i++)
            scanf("%d%d%d%d%d%d%d%d", &W[i].s.x, &W[i].s.y, &W[i].s.z, &W[i].t.x, &W[i].t.y, &W[i].t.z, &W[i].start, &W[i].cost);
    
        //dis[i][j]表示从第i个虫洞的终点走到第j个虫洞的出发点的时间
        for (int i = 0; i <= sink; i++)
            for (int j = 0; j <= sink; j++) 
                dis[i][j] = distance(i, j);
    }
    
    int pre[N], d[N];
    void solve() {
    
        for (int i = 0; i <= sink; i++) {
            d[i] = INF;
            pre[i] = -1;
        }
        d[source] = 0;
    
        while (1) {
            int tmp;
            bool flag = false;
            //找最短路
            for (int i = 0; i <= sink; i++)
                for (int j = 0; j <= sink; j++) {
                    tmp = max(d[i] + dis[i][j], W[j].start) + W[j].cost;
                    if (tmp < d[j]) {
                        d[j] = tmp;
                        pre[j] = i;
                        flag = true;
                    }
                }
    
            //不用更新了
            if (!flag) {
                printf("%d
    ", d[sink]);
                return ;
            }
    
            for (int i = 0; i <= sink; i++) {
                int k = i;
                //推断有没有环
                for (int j = 0; j <= sink && k != -1; j++)  k = pre[k];
                if (k == -1) continue;
                //找出更新的值,破除这个负环,更新的值就是到达起点的值和生成时间的差的最小值。由于在负环内能够等待到生成时间
                int Min = d[pre[k]] + dis[pre[k]][k] - W[k].start;
                for (int j = pre[k]; j != k; j = pre[j])
                    Min = min(d[pre[j]] + dis[pre[j]][j] - W[j].start, Min);
                //假设不存在负环了
                if (Min <= 0) continue;
                //更新负环内的点的距离,破解负环
                    d[k] -= Min;
                for (int j = pre[k]; j != k; j = pre[j])
                    d[j] -= Min;
            }
        }
    }
    
    int main() {
        int test;
        scanf("%d", &test);
        while (test--) {
            init();
            solve();
        }
        return 0;
    }
    
  • 相关阅读:
    1.4.2.3. SETUP(Core Data 应用程序实践指南)
    1.4.2.2. PATHS(Core Data 应用程序实践指南)
    1.4.2.1. FILES(Core Data 应用程序实践指南)
    1.4.2. 实现 Core Data Helper 类(Core Data 应用程序实践指南)
    1.4.1. Core Data Helper 简介(Core Data 应用程序实践指南)
    1.4. 为现有的应用程序添加 Core Data 支持(Core Data 应用程序实践指南)
    1.3.2. App Icon 和 Launch Image(Core Data 应用程序实践指南)
    1.3.1. 新建Xcode项目并设置故事板(Core Data 应用程序实践指南)
    php验证邮箱是否合法
    如何使js函数异步执行
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/8409089.html
Copyright © 2011-2022 走看看