PAT 1018. Public Bike Management

【题目链接】

这题就是先求最短路径,当有多条最短路径的时候按照如下原则择优:sent的自行车较少的更优,如果sent的自行车数量相同,则take back的自行车数量最少的更优。

第一次提交的时候只过了4个case,原因在于:只要前面station的自行车数量不足,就必须从PBMC派送自行车,无论后面路径上的自行车数量是否有多余,也就是说是一个不可逆转的过程。后来改写了程序,在Dijkstra算法的基础上,逐步地对sentBike和backBike进行累加,提交后第7个case不过,无奈之下只好百度,发现不能再Dijkstra的时候同时更新自行车的sentBike和backBike,因为它们不满足最优子结构性质。只能用Dijkstra算出最短距离,然后用dfs搜索最优路径。

第7个case不过的程序:

//第7个case不过,因为不满足最优子结构,不能将sentBike简单的累加
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
using namespace std;

const int INF = 10000000;
const int MAXV = 505;
int Cmax, N, Sp, M;
int sentBike[MAXV] = {0}, backBike[MAXV] = {0};
int d[MAXV]; //最短距离数组
int C[MAXV]; //C[i]表示第i个station的自行车数量
int path[MAXV]; //path[i]存放第i个点的前驱顶点
int G[MAXV][MAXV]; //图的邻接矩阵
bool vis[MAXV] = {false}; //标记顶点是否被访问

void Dijkstra()
{
    d[0] = 0, path[0] = -1, C[0] = 0;
    for(int i = 0; i <= N; i++)
    {
        int u = -1, MIN = INF;
        for(int j = 0; j <= N; j++)
        {
            if(!vis[j] && d[j] < MIN)
                MIN = d[u = j];
        }
        if( u == -1) return;
        vis[u] = true;
        for(int v = 0; v <= N; v++)
            if(!vis[v])
            {
                int count = Cmax / 2 - C[v];
                if(d[u] + G[u][v] == d[v])
                {
                    if(sentBike[u] + max(0, count) < sentBike[v])
                    {
                        sentBike[v] = sentBike[u] + max(0, count); //更新sentBike[v]
                        path[v] = u;
                    }
                    else if(sentBike[u] + max(0, count) == sentBike[v])
                    {
                        if(backBike[u] - min(0, count) < backBike[v])
                        {
                            backBike[v] = backBike[u] - min(0, count);//更新backBike[v]
                            path[v] = u;
                        }
                    }
                }
                else if(d[u] + G[u][v] < d[v])
                {
                    d[v] = d[u] + G[u][v];
                    path[v] = u;

                    if(count >= 0)
                    {
                        if(backBike[u] - count > 0)
                        {
                            backBike[v] = backBike[u] - count;
                            sentBike[v] = sentBike[u];
                        }
                        else
                        {
                            backBike[v] = 0;
                            sentBike[v] = sentBike[u] + count - backBike[u];
                        }
                    }
                    else
                    {
                        sentBike[v] = sentBike[u];
                        backBike[v] = backBike[u] - count;
                    }
                }
            }
    }
}

void output()
{
    vector<int> vi;
    int u = Sp;
    while(path[u] != -1)
    {
        vi.push_back(u);
        u = path[u];
    }
    vi.push_back(0);
    cout << sentBike[Sp] << " ";
    for(int i = vi.size() - 1; i >=0; i--)
    {
        cout << vi[i];
        if(i) cout << "->";
    }
    cout << " " << backBike[Sp] << endl;
}

int main()
{
    //freopen("in_1018.txt", "r", stdin);
    cin >> Cmax >> N >> Sp >> M;
    for(int i = 1; i <= N; i++)
        cin >> C[i];
    for(int i = 0; i <= N; i++) //初始化邻接矩阵G
        for(int j = 0; j <= N; j++)
            G[i][j] = INF;
    fill(d, d + MAXV, INF); //初始化距离为无穷大
    int start, end, time;
    for(int i = 0; i < M; i++)
    {
        cin >> start >> end >> time;
        G[start][end] = G[end][start] = time;
    }
    Dijkstra();
    output();
}

全部AC的程序:

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
using namespace std;

const int INF = 10000000;
const int MAXV = 505;
int Cmax, N, Sp, M;
int sentBike = INF, backBike = INF;
int d[MAXV]; //最短距离数组
int C[MAXV]; //C[i]表示第i个station的自行车数量
int G[MAXV][MAXV]; //图的邻接矩阵
bool vis_dij[MAXV] = {false}; //标记顶点是否被访问
bool vis_dfs[MAXV] = {false};
int curTime = 0; //当前花费的时间
int curSentBike, curBackBike; //当前需要从PBMC派出去的和带回PBMC的自行车数量
vector<int> path; //符合条件的最短路径
vector<int> curPath; //dfs过程中遍历的路径

void Dijkstra()
{
    d[0] = 0, C[0] = 0;
    for(int i = 0; i <= N; i++)
    {
        int u = -1, MIN = INF;
        for(int j = 0; j <= N; j++)
            if(!vis_dij[j] && d[j] < MIN)
                MIN = d[u = j];
        if(u == -1) return;
        vis_dij[u] = true;
        for(int v = 0; v <= N; v++)
            if(!vis_dij[v] && d[u] + G[u][v] < d[v])
                d[v] = d[u] + G[u][v];
    }
}

bool judge(vector<int> curPath) //按照题意选择最优的最短路径
{
    curSentBike = curBackBike = 0;
    for(int i = 0; i < curPath.size(); i++)
    {
        int v = curPath[i];
        int count = Cmax / 2 - C[v];
        if(count >= 0)
        {
            if(curBackBike - count > 0) curBackBike -= count;
            else
            {
                curSentBike += count - curBackBike;
                curBackBike = 0;
            }
        }
        else curBackBike -= count;
    }
    //优先选择派出的自行车数量最少的最短路径,其次再选带回最少的最短路径
    if(curSentBike != sentBike) return curSentBike < sentBike;
    else return curBackBike < backBike;
}

void dfs(int cur) //深度优先搜索最短路径
{
    if(cur == Sp)
    {
        if(curTime == d[Sp] && judge(curPath))
        {
            path = curPath;
            sentBike = curSentBike;
            backBike = curBackBike;
        }
        return;
    }
    for(int i = 1; i <= N; i++)
    {
        if(G[cur][i] != INF && !vis_dfs[i])
        {
            vis_dfs[i] = true;
            curPath.push_back(i);
            curTime += G[cur][i];
            dfs(i);
            vis_dfs[i] = false;
            curPath.pop_back();
            curTime -= G[cur][i];
        }
    }
}

void print()
{
    cout << sentBike << " 0";
    for(int i = 0; i < path.size(); i++)
        cout << "->" << path[i] ;
    cout << " " << backBike << endl;
}

int main()
{
    //freopen("in_1018.txt", "r", stdin);
    cin >> Cmax >> N >> Sp >> M;
    for(int i = 1; i <= N; i++)
        cin >> C[i];
    for(int i = 0; i <= N; i++) //初始化邻接矩阵G
        for(int j = 0; j <= N; j++)
            G[i][j] = INF;
    fill(d, d + MAXV, INF); //初始化距离为无穷大
    int start, end, time;
    for(int i = 0; i < M; i++)
    {
        cin >> start >> end >> time;
        G[start][end] = G[end][start] = time;
    }
    Dijkstra();
    dfs(0);
    print();
}


附件


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值