PAT A1018 Public Bike Management(30)

来源:互联网 发布:mac开机黑屏有进度条 编辑:程序博客网 时间:2024/05/16 10:52

题意

  • N个车站和一个管理中心,给定终点,选取管理中心到终点的最短路径,若有多条最短路径,要根据一些奇怪的标准从中选取一条唯一的最短路径(首先最小take其次最小return)。

注意

  1. 这道题肯定先要用dijkstra,然后问题来了,takereturn值在路径上不满足传递性!这就是说,给定终点x和到该点的最优路径0~x(最短路径里按照标准选取的唯一),其子问题(终点为0~x中间某点y)的最优路径不一定是0~x中的0~y,反例如下。

    10 4 4 5 //原问题:0~4 //子问题:0~3
    4 8 9 0
    0 1 1
    1 2 1
    1 3 2
    2 3 1
    3 4 1

  2. 这道题还有个陷阱,其实没有说清。如下,车站的调整必须是从中心出发到目的车站连续的过程,返程不能调整。

    Finally after another space, output the number of bikes that we must take back to PBMC after the condition of Sp is adjusted to perfect.

  3. 因为不满足传递性,所以不能在dijkstra中的更新路径部分应用标准,所以,要么记录前驱,之后dfs遍历多条最短路径;要么记录完整的最短路径,这样的话需要vector<vector<int>> p[Nmax],每个结点占有一个二维数组。

代码

#include <iostream>#include <algorithm>#include <vector>#include <climits>using namespace std;const int Nmax = 501;int Cmax, N, Sp, M, C2;int bike[Nmax];int road[Nmax][Nmax];int take, rtn;int dist[Nmax];bool S[Nmax];vector<vector<int>> p[Nmax];       void DIJKSTRA(int s0){    fill(S, S + Nmax, false);    fill(dist, dist + Nmax, INT_MAX);    dist[0] = 0;    vector<int> v;    v.push_back(0);    p[0].push_back(v);    for (int j = 0; j <= N; j++)    {        int min = INT_MAX;        int k;        for (int i = 0; i <= N; i++)        {            if (!S[i] && dist[i] < min)            {                min = dist[i];                k = i;            }        }        S[k] = true;        for (int i = 0; i <= N; i++)        {            if (!S[i] && road[k][i] != INT_MAX)            {                if (dist[k] + road[k][i] < dist[i])                {                    dist[i] = dist[k] + road[k][i];                    p[i].clear();                                 ////                    p[i] = p[k];                    for (int l = 0; l < p[i].size(); l++)                        p[i].at(l).push_back(i);                }                else if (dist[k] + road[k][i] == dist[i])                {                       for (int l = 0; l < p[k].size(); l++)                    {                        p[i].push_back(p[k].at(l));                        p[i].at(p[i].size() - 1).push_back(i);                    }                }               ////多条最短路径全部记录            }        }    }}int select_optimal_road(int sp)         {    int opt = -1;    take = rtn = INT_MAX;    vector<vector<int>> v = p[sp];    for (int i = 0; i < v.size(); i++)    {        vector<int> v0 = v.at(i);        int tk = 0, rt = 0;        for (int j = 1; j < v0.size(); j++)        {            if (bike[v0.at(j)] > C2)                rt += bike[v0.at(j)] - C2;            else if(bike[v0.at(j)] < C2)            {                if (rt > C2 - bike[v0.at(j)])                    rt -= C2 - bike[v0.at(j)];                else                {                    tk += C2 - bike[v0.at(j)] - rt;                    rt = 0;                }            }        }        if (tk < take)        {            opt = i;            take = tk;            rtn = rt;        }        else if (tk == take && rt < rtn)        {            opt = i;            rtn = rt;        }    }    return opt;}int main(){    cin >> Cmax >> N >> Sp >> M;    C2 = Cmax / 2;    for (int i = 1; i <= N; i++)        cin >> bike[i];    int r1, r2;    fill(road[0], road[0] + Nmax*Nmax, INT_MAX);    for (int i = 0; i < M; i++)    {        cin >> r1 >> r2;        cin >> road[r1][r2];        road[r2][r1] = road[r1][r2];    }    DIJKSTRA(0);    int o = select_optimal_road(Sp);    vector<int> v = p[Sp].at(o);    cout << take << " ";    for (int i = 0; i < v.size(); i++)    {        if (i == 0)            cout << v.at(i);        else cout << "->" << v.at(i);    }    cout << " " << rtn;    return 0;}
1 0
原创粉丝点击