欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

PAT甲级1018 Public Bike Management (30分)|C++实现

程序员文章站 2022-06-07 14:40:35
...

一、题目描述

原题链接
PAT甲级1018 Public Bike Management (30分)|C++实现

Input Specification:

PAT甲级1018 Public Bike Management (30分)|C++实现

​​Output Specification:

PAT甲级1018 Public Bike Management (30分)|C++实现

Sample Input:

10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1

Sample Output:

3 0->2->3 0

二、解题思路

算是一道比较复杂的30分题,但是基本思路还算清晰,用Dijkstra算法找最短路径,用一个vector的数组来记录最短路径中每个点的前一个点,用dfs从后往前检索,记录路径,寻找需要回收或者需要发放的自行车最少的一条。思路就是这样,但是具体实现的细节非常多,代码也很长,这些细节都写在代码的注释中了。

三、AC代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int INF = 99999999;
int cmax, n, sp, m; //一个地点最多存放的车辆数,站点数,问题站点,图的边数
int minNeed = INF, minback = INF; //最少需要的车辆,最少回收的车辆
int e[510][510], dis[510], weight[510]; //邻接矩阵,到每个点的最短距离,每个顶点当前的车辆数-cmax/2
bool visit[510]; //Dijkstra算法中是否已经更新到最短值的标记
vector<int> pre[510], path, temppath;
void dfs(int v)
{
  temppath.push_back(v);
  if(v == 0)
  {
    int need=0, back=0;
    for(int i=temppath.size()-1; i>=0; i--)
    {
      int id = temppath[i];
      if(weight[id] > 0)    //说明应该从这个站点回收自行车
        back += weight[id];
      else
      {
        if(back > -weight[id])  //说明已经回收的车辆数大于需要给这个站点的车辆数
          back += weight[id];   //注意这里weight[id]是个负数,所以实际上是回收的车辆减去给这个站点的车辆
        else    //说明总体需要我们从起点运车
        {
          need += (-weight[id] - back);
          back = 0; //把需要还的车辆数设置为0
        }
      }
    }
    if(need < minNeed)  //如果当前的路径需要的车辆数更加少
    {
      minNeed = need;
      minback = back;
      path = temppath;
    }
    else if(need == minNeed && back < minback)  //当前的路径回收的车辆更加少
    {
      minback = back;
      path = temppath;
    }
    temppath.pop_back();    //退回到之前的顶点
    return;
  }
  for(int i=0; i<pre[v].size(); i++)
    dfs(pre[v][i]); //对该点的前面所有点(具有相同最短距离的点)进行dfs
  temppath.pop_back();  //退回之前的顶点
}
int main()
{
  fill(e[0], e[0]+510*510, INF);
  fill(dis, dis + 510, INF);
  scanf("%d%d%d%d", &cmax, &n, &sp, &m);
  for(int i=1; i<=n; i++)
  {
    scanf("%d", &weight[i]);
    weight[i] = weight[i] - cmax/2;
  }
  for(int i=0; i<m; i++)
  {
    int a, b;
    scanf("%d%d", &a, &b);
    scanf("%d", &e[a][b]);
    e[b][a] = e[a][b];
  }
  dis[0] = 0;   //开始Dijkstra算法
  for(int i=0; i<=n; i++)
  {
    int u=-1, minn = INF;
    for(int j=0; j<=n; j++)
    {
      if(visit[j] == false && dis[j] < minn)
      {
        u = j;
        minn = dis[j];
      }
    }
    if(u == -1)	break;
    visit[u] = true;
    for(int v=0; v<=n; v++)
    {
      if(visit[v] == false && e[u][v] != INF)
      {
        if(dis[v] > dis[u] + e[u][v])
        {
          dis[v] = dis[u]+e[u][v];
          pre[v].clear();
          pre[v].push_back(u);
        }
        else if(dis[v] == dis[u] + e[u][v])
          pre[v].push_back(u);
      }
    }
  } //Dijkstra算法结束
  dfs(sp);
  printf("%d 0", minNeed);
  for(int i=path.size()-2; i>=0; i--)   //因为我们把0放在前面输出了,所以这里是从size()-2开始循环
    printf("->%d", path[i]);
  printf(" %d", minback);
}
相关标签: PAT Advanced