PAT甲级——1001.Public Bike Management

原题链接




Figure 1

题目翻译:

杭州市有公共自行车服务,为来自世界各地的游客提供了极大的方便。 人们可以在任何一个车站租一辆自行车,并将其返回到城市中的任何其他车站。 公共自行车管理中心(PBMC)持续监控所有车站的实时通行能力。 据说,如果一个电台刚满一半,它就处于完美状态。 如果某个电台已满或已空,PBMC将收集或发送自行车以调整该电台的状态以完善。 此外,途中的所有车站也将进行调整。 当报告问题站时,PBMC将始终选择到达该站的最短路径。 如果有多条最短路径,那么将选择PBMC发送的最少数量的自行车。

图1举例说明。 站点由顶点表示,道路对应于边缘。 边缘上的数字是从另一端站到另一端站所花费的时间。 写在顶点S内的数字是存储在S处的当前自行车数量。假设每个站点的最大容量为10.为了解决S3中的问题,我们有两条不同的最短路径:1. PBMC→S1→S3。 在这种情况下,必须从PBMC发送4辆自行车,因为我们可以从S1收集1辆自行车,然后将5辆自行车带到S3,这样两个车站都将处于完美状态。 2. PBMC→S2→S3。 此路径需要与路径1相同的时间,但只有3辆PBMC发送自行车,因此是将要选择的自行车。

每个输入文件都包含一个测试用例。 对于每种情况,第一行包含4个数字:Cmax(<= 100),始终为偶数,是每个站的最大容量; N(<= 500),车站总数; Sp,问题站的索引(站号从1到N,PBMC由顶点0表示); M是道路的数量。 第二行包含N个非负数Ci(i = 1,… N),其中每个Ci分别是当前在Si上的自行车数量。 然后是M行,每行包含3个数字:Si,Sj和Tij,它们描述了在站点Si和Sj之间移动的时间Tij。 一行中的所有数字用空格分隔。

对于每个测试用例,将结果打印在一行中。 首先输出PBMC必须发送的自行车数量。 然后在一个空格后输出格式为:0-> S1 - > …-> Sp的路径。 最后,在Sp的条件调整到完美之后,输出我们必须带回PBMC的自行车数量。 请注意,如果这样的路径不是唯一的,那么输出需要最少数量的自行车的路线,我们必须将它们带回PBMC。 测试的数据保证这样的路径是独一无二的。

问题分析及解题思路:

很明显这道题更适合DFS算法,并不需要用Dijkstra算法,只需要在深度遍历非连通图时加上判断是否到达Sp站,以及是否是最短路径和最小携带自行车数和最小带回自习车数。这里不用栈来记录当前路径和最短路径,用vector更方便。另外题目意思可能理解错了,从0站到sp站的过程中修正所有点,但是不会把多余的自行车再送回之前的点,比如一条路上bike数为3 7,是send2,back2,而不是back0。

dfs算法分析
bfs算法分析
Dijkstra算法分析

#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
#pragma warning(disable:4996)
#define MAX 505
#define INF 10000

int maxCap, N, endStation, numRoad;//依次接收第一行数据
int vex; //设置为N+1,便于循环判断
int graph[MAX][MAX];//存放各结点和边,有向图
int bike[MAX];//存放各站自习车数量
#define PF maxCap/2//各站处于完美状态的自行车数量

vector<int> curpath;//当前路径
vector<int> shortpath;
int minSend = INF, minBack = INF;
int minTime = INF;
int curSend = 0, curBack = 0;
int curTime = 0;
bool visit[MAX] = { 0 };//判断某条边是否被访问过
/*
图的深度优先搜索遍历类似于二叉树的先序遍历。它的基本思想是:首先访问出发点v,并将其标
记为已访问过;然后选取与v邻接的未被访问的任意一个顶点w,并访问它;再选取与w邻接的为被
访问的任一顶点并访问,以此重复进行。当一个顶点所有的邻接顶点都被访问过时,则依次退回
到最近被访问过的顶点,若该顶点还有其他邻接顶点未被访问,则从这些未被访问的顶点中去一
个并重复上述访问过程,直至图中所有顶点都被访问过为止。
*/
void dfs(int startStation) 
{
    if (curTime > minTime)
        return;
    if (startStation == endStation)
    {
        //到达目标点,看是否最优 
        if (curTime < minTime) 
        {
            minTime = curTime;
            minSend = curSend;
            minBack = curBack;
            shortpath = curpath;
        }
        else if (curTime == minTime) 
        //有多条最短路径,则比较从总站的自行车携带数或者返回总站自习车数
        {
            if (curSend < minSend || (curSend == minSend && curBack < minBack)) 
            {
                minSend = curSend;
                minBack = curBack;
                shortpath = curpath;
            }
        }
        return;
    }
    for (int i = 1; i < vex; i++) 
    {
        if (visit[i] == true || graph[startStation][i] == INF)
            continue;//如果这条边被访问过,或者不存在次路径,则跳过
        int lastsend = curSend;
        int lastback = curBack;
        //计算到达当前点的send和back数 
        if (bike[i] + curBack < PF) 
        {
            curSend += PF - bike[i] - curBack;
            curBack = 0;
        }
        else 
        {
            curBack = bike[i] + curBack - PF;
        }
        visit[i] = true;//置i站被访问过
        curpath.push_back(i);
        curTime += graph[startStation][i];
        dfs(i);//递归,把i站当做起始站(中心站)    深度优先遍历非连通图
        //下面是回溯,回到刚访问的站,访问另一与他相邻的站
        curpath.pop_back();
        visit[i] = false;
        curTime -= graph[startStation][i];
        curSend = lastsend;
        curBack = lastback;
    }
}
int main() 
{
    //接收第一行
    cin >> maxCap >> N >> endStation >> numRoad;
    //初始化,距离置为INF 
    vex = N + 1;
    for (int i = 0; i < vex; i++) 
    {
        for (int j = 0; j < vex; j++) 
        {
            graph[i][j] = graph[j][i] = INF;
        }
    }
    //存放各站的自行车数量
    for (int i = 1; i < vex; i++)
    {
        cin >> bike[i];
    }
    //构造图
    for (int k = 0; k < numRoad; k++)
    {
        int i, j;
        cin >> i >> j;
        cin >> graph[i][j];
        graph[j][i] = graph[i][j];
    }

    dfs(0);//从中心站开始遍历

    printf("%d 0", minSend);
    for (int i = 0; i < shortpath.size(); i++)
    {
        printf("->%d", shortpath[i]);
    }
    printf(" %d", minBack);
    system("pause");
    return 0;
}

以上代码更改自https://blog.csdn.net/ywy0ywy/article/details/45770693

猜你喜欢

转载自blog.csdn.net/wardseptember/article/details/80369141