zoukankan      html  css  js  c++  java
  • PAT甲级1018Public Bike Management

    题目链接

    https://pintia.cn/problem-sets/994805342720868352/problems/994805489282433024

    题解

    题目要求

    • 如果有多个最短路径,则选择PBMC送出自行车的数量最少的路径

      如果还是有多条最短路径,那么就选择从车站带回的自行车数目最少的(带回的时候是不调整路过的车站的)

    • PBMC携带或者从经过的车站收集一定数量的自行车前往某车站,并使路过的车站都达到半满。

    • 输入

      • Cmax:不超过100,偶数,每个站点中最多有多少辆自行车
      • N:不超过500,站点的数量,站点索引为[1,N],PBMC索引为0
      • Sp:有问题的站点
      • M:边的数量
      • N个站点中自行车的数量
      • M条边
    • 输出

      • PBMC要送多少辆自行车
      • 路径
      • 要送多少辆自行车到PBMC

    解题思路

    PAT甲级1030Travel Plan和这题很类似,但比这题简单,大概是比这题少了一个DFS。

    • dijkstra

      除了要求出PBMC到所有结点的最短路径长度,还要在算法过程中记录所有最短路径上每个结点的前一个结点,进而进行下一步的DFS。

    • DFS

      运行dijkstra算法后,已经记录了所有最短路径上每个结点的前一个结点(可以有多个),然后从结点sp开始DFS,相当于从sp走到PBMC。

      DFS过程中要记录当前路径

    • 求路径上多余或缺少的自行车的数量

      DFS过程中,如果当前结点是PBMC,则从PBMC走到sp,求多余或缺少的自行车的数量,再和全局最小值比较、更新

    代码

    // Problem: PAT Advanced 1018
    // URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805489282433024
    // Tags: 最短路 dijkstra BFS DFS 单源最短路 图
    
    #include <iostream>
    #include <climits>
    #include <vector>
    using namespace std;
    
    const int INF = INT_MAX;
    const int MAXN = 505;
    int cmax, n, sp, m;
    int minStationNeed = INF, minStationExtra = INF; // PBMC最少需要送出多少辆车,最少要送多少辆车到PBMC
    int e[MAXN][MAXN]; // 车站间的距离
    int dis[MAXN]; // PBMC到各车站的最短路径的长度
    int extraBikeNum[MAXN]; // 各车站中有多少辆自行车是多余的
    bool visited[MAXN]; // 是否已求出PBMC到各车站的最短路
    vector<int> pre[MAXN]; // 在保证路径最短的前提下,最短路径中每个车站的前一个车站
    vector<int> path;
    vector<int> tempPath;
    
    void dfs(int v){
        // 遍历当前结点
        tempPath.push_back(v);
        if (v == 0){ // 此时已形成一条最短路径的逆序,存储在tempPath中
            int stationNeed = 0, stationExtra = 0;
            for (int i = tempPath.size() - 1; i >= 0; i--){
                int u = tempPath[i];
                if (extraBikeNum[u] > 0){ // 当前站点中自行车数量超过容量的一半,则可以送给后面的车站或者送回PBMC
                    stationExtra += extraBikeNum[u];
                }
                else if (extraBikeNum[u] < 0){ // 当前站点中自行车数量少于容量的一半
                    if (stationExtra + extraBikeNum[u] >= 0){ // 前边车站多出来的自行车足够使当前车站半满
                        stationExtra += extraBikeNum[u];
                    }
                    else{
                        stationNeed -= (stationExtra + extraBikeNum[u]);
                        stationExtra = 0;
                    }
                }
                
            }
            if (stationNeed < minStationNeed){
                path = tempPath;
                minStationNeed = stationNeed;
                minStationExtra = stationExtra;
            }
            else if (stationNeed == minStationNeed && stationExtra < minStationExtra){
                path = tempPath;
                minStationExtra = stationExtra;
            }
        }
        // DFS
        for (int i= 0; i < pre[v].size(); i++)
            dfs(pre[v][i]);
        // 回溯
        tempPath.pop_back();
    }
    
    int main()
    {
        // 初始化
        fill(e[0], e[0] + MAXN * MAXN, INF);
        fill(dis, dis + MAXN, INF);
    
        // 获取输入
        scanf("%d %d %d %d", &cmax, &n, &sp, &m);
        for (int i = 1; i <= n; i++){
            scanf("%d", &extraBikeNum[i]);
            extraBikeNum[i] = extraBikeNum[i] - cmax / 2;
        }
            
        int a, b, c;
        for (int i = 0; i < m; i++){
            scanf("%d %d %d", &a, &b, &c);
            e[a][b] = e[b][a] = c;
        }
    
        dis[0] = 0; // PBMC为起点
        for (int i = 0; i <= n; i++){
            int u = -1, minDis = INF;
            for (int j = 0; j <= n; j++){
                if (!visited[j] && dis[j] < minDis){
                    minDis = dis[j];
                    u = j;
                }
            }
            if (u == -1) break;
            visited[u] = true;
            for (int v = 0; v <= n; v++){
                if (!visited[v] && e[u][v] != INF){
                    if (dis[u] + e[u][v] < dis[v]){
                        dis[v] = dis[u] + e[u][v];
                        pre[v].clear(); // 新的最短路径,所以要clear
                        pre[v].push_back(u); // u是v的最短路径中v的前一个车站
                    }
                    else if (dis[u] + e[u][v] == dis[v]){
                        pre[v].push_back(u); // u是v的最短路径中v的前一个车站
                    }
                }
            }
        }
    
        dfs(sp);
        printf("%d 0", minStationNeed);
        for (int i = path.size() - 2; i >= 0; i--)
            printf("->%d", path[i]);
        printf(" %d", minStationExtra);
        return 0;
    }
    

    参考链接

    https://blog.csdn.net/liuchuo/article/details/52316405


    作者:@臭咸鱼

    转载请注明出处:https://www.cnblogs.com/chouxianyu/

    欢迎讨论和交流!


  • 相关阅读:
    RabbitMQ 集群与高可用配置
    ManifoldJS
    Top JavaScript Frameworks, Libraries & Tools and When to Use Them
    AngularJS 的安全Apply
    node js 常用模块
    微软发布了ASP.NET WebHooks预览版
    leaflet 了解
    messagepcak 资料
    fastBinaryJSON
    jQuery的图像裁剪插件Jcrop
  • 原文地址:https://www.cnblogs.com/chouxianyu/p/13690906.html
Copyright © 2011-2022 走看看