1018 Public Bike Management

  • 该站点图是无向图

路径优先级:
(1)路径取得最小值 (Dijkstra()已经实现)

(2)在(1)都满足的条件下,PBMC发出的bike需要最小

(3)在(1)(2)都满足的条件下,带回来的bike需要最小;

  • 先Dijkstra求出所有最短路径
  • 再遍历每条路径,根据bike调整到half_full逻辑得出 PBMC 发出和带回 的 bike数,
  • 更新得到最终的最优路径
#include <limits>
const int INF = numeric_limits<int>::max(); 
int C, N, Sp, M;
int perfect;

struct Edge
{
    int to, weight;
};

int bikes_of_each_station[502] = {0};

// 根据前驱站点回溯获取完整路径
void get_all_paths(const vector<vector<int>> &predecessors,
                   vector<vector<int>> &all_paths, 
                   vector<int> path, 
                   int cur)
{
    if(cur == 0)
    {
        // 回溯前驱站点得到的路径是逆序的,将其反转
        reverse(path.begin(), path.end());
        all_paths.push_back(path);
        return;
    }
    for(auto p : predecessors[cur])
    {
        path.push_back(p);
        get_all_paths(predecessors, all_paths, path, p);
        path.pop_back();
    }
}

void Dijkstra(const vector<vector<Edge>> &graph, int start)
{
    // Dijkstra求所有最短路径并保存
    vector<int> dist(N + 1, INF);
    vector<bool> visited(N + 1, false);
    vector<vector<int>> predecessors(N + 1);
    dist[start] = 0;
    for(int i = 0; i <= N; ++i)
    {
        int u = -1, minDist = INF;
        for(int j = 0; j <= N; ++j)
        {
            if(!visited[j] && dist[j] < minDist)
            {
                minDist = dist[j];
                u = j;
            }
        }
        if(u == -1)
            break;
        visited[u] = true;
        for(const auto &edge : graph[u])
        {
            int v = edge.to, w = edge.weight;
            if(!visited[v])
            {
                int newDist = dist[u] + w;
                if(newDist < dist[v])
                {
                    dist[v] = newDist;
                    predecessors[v].clear();
                    predecessors[v].push_back(u);
                }
                else if(newDist == dist[v])
                {
                    predecessors[v].push_back(u);
                }
            }
        }
    }

    // 求出所有最短路径
    vector<int> path = {Sp};
    vector<vector<int>> all_paths;
    get_all_paths(predecessors, all_paths, path, Sp);

    // 找最佳路径,从PBMC开始,沿途调整,得到该路径需要的 送出 和 带回 的数量
    int paths_count = all_paths.size();
    int min_send = INF, min_back = INF, best_path_idx = 0;
    for(int i = 0; i < paths_count; ++i)
    {
        vector<int> &cur_path = all_paths[i];
        
        int path_len = cur_path.size();
        int cur_take = 0, cur_send = 0, cur_back = 0;
        
        for(int j = 1; j < path_len; ++j)
        {
            int sta = cur_path[j];
            // 当前站大于perfect,需将其多余的带走
            if(bikes_of_each_station[sta] > perfect)
            {
                cur_take += (bikes_of_each_station[sta] - perfect);
            }
            //  当前站小于perfect,需补充
            else if(bikes_of_each_station[sta] < perfect)
            {
                int still_need = perfect - bikes_of_each_station[sta];
                // 当前带的够补充
                if(still_need <= cur_take)
                {
                    cur_take -= still_need;
                }
                // 当前带的不够补充,需从源头增加送出
                else
                {
                    cur_send += (still_need - cur_take);
                    cur_take = 0;
                }
            }
        }

        // 最后带回的就是最后还有的
        cur_back = cur_take;

        // 优先选送出少的路径
        if(cur_send < min_send)
        {
            min_send = cur_send;
            min_back = cur_back;
            best_path_idx = i;
        }
        // 再选最后带回少的路径
        else if(cur_send == min_send)
        {
            if(cur_back < min_back)
            {
                min_send = cur_send;
                min_back = cur_back;
                best_path_idx = i;
            }
        }
        
    }

    // 打印最终的最佳路径
    const vector<int> &p = all_paths[best_path_idx];
    cout << min_send << " ";
    for(int i = 0; i < p.size(); ++i)
    {
        cout << p[i];
        if(i != p.size() - 1)
            cout << "->";
    }
    cout << " " << min_back;
}

int main()
{
    cin >> C >> N >> Sp >> M;
    perfect = C / 2;    // haff_full
    
    for(int i = 1; i <= N; ++i)
        cin >> bikes_of_each_station[i];

    vector<vector<Edge>> graph(N + 1);

    // 这里的站点图是 无向图!
    auto add_edge = [&](int u, int v, int w){
        graph[u].push_back({v, w});
        graph[v].push_back({u, w});
    };

    int u, v, w;
    for(int i = 0; i < M; ++i)
    {
        cin >> u >> v >> w;
        add_edge(u, v, w);
    }
    
    Dijkstra(graph, 0);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值