1018 Public Bike Management (30分)

Posted wsshub

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1018 Public Bike Management (30分)相关的知识,希望对你有一定的参考价值。

技术图片

 这题也很好。涉及多条最短路径问题。使用Dijkstra找到多条最短路径,再使用DFS对路径进行回溯选取最佳的最短路径。

1.只用Dijkstra不能拿满分。

2.最短路径的优先级是(由高到低):路径最短的;从PBMC取走的自行车数目最少的;从车站取回的自行车数目最少的。

3.存储多条最短路径的策略是,用二维数组vector<vector<int> >prev代替原来的一维数组存储前驱节点。思路是:

在Dijkstra算法中,专心求解前驱数组。
if
(发现距离更短的路径){ 更新存放最短路径的数组; 清空这个点对应的前驱数组; 将这个点存入前驱数组 }else if(发现距离相同的路径){ 将这个点存入前驱数组 }

4.使用dfs遍历前驱数组。步骤是:

int bestValue;    //存放第二标尺最优值(第一标尺是路径长短,第二标尺在本题中是从PBMC取走的自行车数目,第三标尺是从车站取回的自行车数目)
vector<int> pre[MAXN];    //前驱节点数组
vector<int> path;    //存放最优路径
vector<int> tempPath;    //存放临时路径

void DFS(int v){    //v为当前访问的节点
    tempPath.push_back(v);    //将v加入临时路径,进入dfs的节点都会被记录,tempPath存放着最短路径
    //DFS的"死胡同",递归边界
    if(v == startPoint){    //遍历到了终点
        int value;                //在此计算第二标尺
        if(value比bestValue更优){    //比较当前第二标尺与之前最优的第二标尺,确定是不是一条更优的路径
            bestValue = value;    //更新最优值
            path = tempPath;       //更新最优路径
        }
    }
    //DFS的"岔路口",递归式
    else{            //v != startPoint,没遍历到终点
        for(int i = 0; i < pre[v].size(); i++){//枚举容器内的所有前驱结点
            DFS(pre[v][i]);                //然后依次遍历
    }
    tempPath.pop_back();    //本节点找完了,删掉。以便遍历其他的
}

 

5.若在全局变量中定义prev,提交到pat会出现错误: error: reference to prev is ambiguous ,原因是和引用的库函数中定义的变量名重合了,解决方法是更改变量名,我就是把prev改成pre。

6.在全局变量中定义数组时,类似vector<int>  data(N)(N是变量)的操作会出错,在全局变量中定义数组,数目一定要是常量。

7.如何更新需要带出的和需要带回的自行车数目,需要想清楚。思路可以是:

//send为需要从PBMC取出的总数目,back是需要带回到PBMC的总数目
从PBMC出发,终点是问题车站
如果车站的数目比“完美数目”多
      则带走多的部分,加到back中记录;
如果比“完美数目”少,则比较back和当前车站缺少的数目
      如果back>当前车站缺少的数目
      表示从车站带出的自行车可以填补这一个车站的空缺,back剩余的数目是(back-当前车站缺少的数目),send值不变
      如果back<=当前车站缺少的数目
      表示从车站带出的自行车不能填补这一个车站的空缺,所有back填补到这一车站,该车站仍有(当前车站缺少的数目-back)的空缺,send加上这个空缺数目,就是需要从PBMC取出的总数目,back归0。
      

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<vector>
  4 #include<algorithm>
  5 #define inf 0x3f3f3f3f
  6 using namespace std;
  7 int C,N,SOS,M;
  8 int minSend=inf,minBack=inf;
  9 vector<int> dis(520,inf);
 10 vector<vector<int> > pre(520);
 11 vector<int> visited(520);
 12 vector<int> bestPath,tempPath;
 13 struct Edge{
 14     int id;
 15     int weight;
 16     Edge(){
 17         id=weight=0;
 18     }
 19 };
 20 int k1,k2,weight;
 21 Edge e;
 22 vector<int> V(520);
 23 vector<vector<Edge> > E(520);
 24 void dfs(int v){
 25     tempPath.push_back(v);//记录这个节点 
 26     if(v==0){//递归边界,终点 ,tempPath记录了其中一条最短路径 
 27         int send=0,back=0;
 28         for(int i=tempPath.size()-1;i>=0;i--){
 29             if(V[tempPath[i]]>0)
 30                 back+=V[tempPath[i]]; //累加需要带回的 
 31             else{
 32                 if(back>abs(V[tempPath[i]]))
 33                    back=back-abs(V[tempPath[i]]);//用需要带回的去补充缺少的 
 34                 else{
 35                    send+=abs(V[tempPath[i]])-back;
 36                    back=0;
 37                 }          
 38              }
 39         }
 40         if(send<minSend){
 41             bestPath=tempPath;
 42             minSend=send;
 43             minBack=back;
 44         }
 45         else if(send==minSend&&back<minBack){
 46             minBack=back;
 47             bestPath=tempPath;
 48        }
 49     }
 50     else//如果不是终点 ,继续dfs 
 51       for(int i=0;i<pre[v].size();i++)//邻居 
 52           dfs(pre[v][i]) ;
 53           
 54     tempPath.pop_back();//第一个运行至此的只能是终点,终点被访问完毕,弹出,末尾是终点之前的节点 x
 55                          // 此后程序退回到第26行,再次对终x进行dfs,如果x没有邻居,则又会运行至此,弹出x,路径又回退,以此类推 
 56                          //即从终点一直回退,访问完所有可能的路径 
 57 }
 58 int main(){ 
 59     scanf("%d%d%d%d",&C,&N,&SOS,&M);
 60     for(int i=1;i<=N;i++){
 61         scanf("%d",&V[i]);
 62         V[i]=V[i]-C/2;
 63     }
 64     for(int i=0;i<M;i++){
 65          scanf("%d%d%d",&k1,&k2,&weight);
 66          e.weight=weight;
 67          e.id=k2;
 68          E[k1].push_back(e);
 69          e.id=k1;
 70          E[k2].push_back(e);
 71     }
 72     dis[0]=0;
 73     int min,m=0;
 74     for(int i=0;i<N+1;i++){
 75         min=inf;
 76         for(int j=0;j<N+1;j++){
 77             if(visited[j]==0&&min>dis[j]){
 78                 m=j;
 79                 min=dis[j];
 80             }
 81         }
 82         visited[m]=1;
 83         for(int j=0;j<E[m].size();j++){
 84             int v=E[m][j].id;
 85             if(visited[v]==0){
 86                 if(dis[m]+E[m][j].weight<dis[v])
 87                 {   dis[v]=dis[m]+E[m][j].weight;
 88                     pre[v].clear();
 89                     pre[v].push_back(m);
 90                  } 
 91                 else if(dis[m]+E[m][j].weight==dis[v])//是else if哦,保证上面的if如果执行了就不会执行这一段 
 92                     pre[v].push_back(m);
 93             }
 94         }
 95     }
 96     dfs(SOS);
 97     printf("%d 0", minSend);
 98     for(int i = bestPath.size() - 2; i >= 0; i--)
 99         printf("->%d", bestPath[i]);
100     printf(" %d", minBack);    
101     return 0;
102 }

 

参考链接:

PAT-A1018 Public Bike Management 题目内容及题解-日沉云起

多条最短路径问题再探-使用Dijkstra+DFS选出并输出最优路径-斐斐のBlog

 

以上是关于1018 Public Bike Management (30分)的主要内容,如果未能解决你的问题,请参考以下文章

1018 Public Bike Management

1018. Public Bike Management (30)

1018 Public Bike Management (30 分)

1018 Public Bike Management (30分)

PAT A1018.Public Bike Management

1018 Public Bike Management (30)(30 分)