⚠️ Dijkstra + DFS | 路径维护、DFS回溯

2019-08-08  本文已影响0人  zilla

1018 Public Bike Management (30 分)

这题看了「算法笔记」才发现细节这么多😭,自己想怕是只能过个样例……

When a problem station is reported, PBMC will always choose the shortest path to reach that station.
If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.
Note that if such a path is not unique, output the one that requires minimum number of bikes that we must take back to PBMC. The judge's data guarantee that such a path is unique.

⚠️注释掉的部分是典型错误,因为要求在去往目的点的路上就调整好,而非往返一次调整好;若往返一次调整好,就只需Dijkstra、计数路径上点与perfect conditon的总差值了。

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>

#define INF 0x3fffffff
using namespace std;
int graph[501][501], ori_bikes[501] = {0}, dist[501];
bool visited[501] = {false};
int Capacity, nn, Target, mm, least_need = INF, least_remain = INF;
vector<int> pre[501], path, temp_path;

void Dijkstra(int root) {
    fill(dist, dist + nn + 1, INF);
    dist[root] = 0;
    for (int i = 0; i <= nn; ++i) { // 0 - nn  nn+1
        int min_dist = INF, curr = -1;
        for (int j = 0; j <= nn; ++j) {
            if (!visited[j] && dist[j] < min_dist) {
                curr = j, min_dist = dist[j];
            }
        }
        if (curr != -1) {
            visited[curr] = true;
            for (int j = 0; j <= nn; ++j) {
                if (graph[curr][j] != INF && !visited[j]) {
                    int new_dist = dist[curr] + graph[curr][j];
                    if (new_dist < dist[j]) {
                        dist[j] = new_dist;
                        pre[j].clear();
                        pre[j].emplace_back(curr);
                    } else if (new_dist == dist[j]) {
                        pre[j].emplace_back(curr);
                    }
                }
            }
        } else {
            printf("not reachable!!!\n");
            return;
        }
    }
}

void DFS(int root) {
    temp_path.push_back(root);
    if (root == 0) {
        int size = temp_path.size(), remain = 0, need = 0;
        for (int i = size - 1; i >= 0; i--) {
            int curr = temp_path[i];
            if (ori_bikes[curr] < 0) {
                int _abs = abs(ori_bikes[curr]);
                if (remain > _abs)
                    remain -= _abs;
                else {
                    need += _abs - remain;
                    remain = 0;
                }
            } else if (ori_bikes[curr] > 0) {
                remain += ori_bikes[curr];
                /*
                    if (ori_bikes[curr] > need) {
                        need = 0;
                        remain += (ori_bikes[curr] - need);
                    } else {
                        need -= ori_bikes[curr];
                    }
                 */
            }
        }
        if (need < least_need) {
            path = temp_path;
            least_need = need;
            least_remain = remain;
        } else if (need == least_need && remain < least_remain) {
            path = temp_path;
            least_remain = remain;
        }
        temp_path.pop_back();
        return;
    }
    for (auto item:pre[root]) {
        DFS(item);
    }
    temp_path.pop_back();
}

int main() {
    scanf("%d%d%d%d", &Capacity, &nn, &Target, &mm);
    Capacity /= 2;
    for (int i = 1; i <= nn; ++i) {
        scanf("%d", &ori_bikes[i]);
        ori_bikes[i] -= Capacity;
    }
    fill(graph[0], graph[0] + 501 * 501, INF);
    int v1, v2, weight;
    for (int i = 0; i < mm; ++i) {
        scanf("%d%d%d", &v1, &v2, &weight);
        graph[v1][v2] = graph[v2][v1] = min(weight, graph[v2][v1]);
    }
    Dijkstra(0);
    DFS(Target);
    printf("%d ", least_need);
    for (int i = path.size() - 1; i >= 0; --i) {
        printf("%d", path[i]);
        if (i > 0) printf("->");
    }
    printf(" %d\n", least_remain);
    return 0;
}
上一篇下一篇

猜你喜欢

热点阅读