Loading

PAT 1018 Public Bike Management (Dijkstra + dfs记录多条最短路径)

 

 

 

 

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
 

题目大意

杭州市的自行车站管理系统,每个站点都有一定数量的自行车,数量处于最大值一半的状态是“perfect condition”(有车可借,有空位可还车),如果数量是0,称之为“problem condition”,需要从调度中心去运送车辆。运送路程中,如果经过自行车站点,会顺带调整该站点的状态,多的车子带走,少的顺带补齐。已知各个自行车站点的通车时间,求问最短的行车路线,如果存在多个最短路线,那么需要补送自行车最少的一个是多少。   

  1. 找最短路径;
  2. 若不唯一,找其中需要送出自行车最少的路径;
  3. 若还不唯一,找其中需要回收自行车最少的路径;

解题思路

题目的本质实质上是求带权单源最短路径,可以使用Dijkstra算法,但可能存在多个最短路径,所以还要在最后的结果中使用深度优先搜索判断哪个是最符合条件的。 

只能沿着最短路径的方向收集多余自行车,分给后面的节点;后面节点多出来的不能填到前面去,只能计入回收总量。

例如路径上自行车数为5->0->10,并不能把最后一个节点上挪5个给中间的,需要送出5个,并回收5个。

测试点5和7。

 

参考文章:

https://blog.csdn.net/zhang35/article/details/104153985

https://blog.csdn.net/CV_Jason/article/details/81385228

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <vector>
  4 
  5 #define INF 1000000000
  6 
  7 using namespace std;
  8 
  9 int dist[510];
 10 vector<int> pre[510];
 11 vector<int> path, tmp;
 12 int g[510][510]; 
 13 int s[510];
 14 int vis[510];
 15 int C, N, Sp, M;
 16 int minNeed = INF;        //需要额外带的自行车
 17 int back = INF;          //需要带回去的自行车 
 18 
 19 /*
 20 10 3 3 3
 21 5 0 10
 22 0 1 1
 23 1 2 1
 24 2 3 1
 25 */
 26 
 27 //先假设最短路唯一,看看能得多少分
 28 void dijkstra (int start)
 29 {
 30     for(int i = 0; i <= N; ++i)
 31     {
 32         dist[i] = INF;
 33         vis[i] = 0;
 34     }
 35     dist[start] = 0;
 36     
 37     while(1)
 38     {
 39         int mark = -1, minDist = INF;
 40         for(int i = 0; i <= N; ++i)
 41         {
 42             if(!vis[i] && dist[i] < minDist)
 43             {
 44                 minDist = dist[i];
 45                 mark = i;
 46             }
 47         }
 48         
 49         if(mark == -1)
 50             break;
 51             
 52         vis[mark] = 1;
 53         
 54         for(int i = 0; i <= N; ++i)
 55         {
 56             if(!vis[i])
 57             {
 58                 if(dist[mark] + g[mark][i] < dist[i])
 59                 {
 60                     dist[i] = dist[mark] + g[mark][i];
 61                     pre[i].clear();
 62                     pre[i].push_back(mark);    // 记录路径 
 63                 }
 64                 else if(dist[mark] + g[mark][i] == dist[i])
 65                 {
 66                     pre[i].push_back(mark);    // 记录路径
 67                 }    
 68             }
 69         }
 70     }
 71     
 72 }
 73 
 74 void dfs(int v)
 75 {
 76     // 深度优先路过的顶点,存入tmp 
 77     tmp.push_back(v);
 78     // 当到达顶点0的时候,开始计算
 79     if(v == 0)
 80     {
 81         int perfectnum = C/2;
 82         int difference;
 83         int need = 0;        //需要带的自行车 
 84         int available = 0;    //可用的(多余的)自行车    
 85         for(int i = tmp.size()-2; i >= 0; --i)
 86         {
 87             if(s[tmp[i]] > perfectnum)     
 88             {
 89                 // 有单车多余 
 90                 difference = s[tmp[i]] - perfectnum;
 91                 available += difference;
 92             }
 93             else if(s[tmp[i]] < perfectnum)
 94             {
 95                 // 单车不够 
 96                 difference = perfectnum - s[tmp[i]];
 97                 if(available >= 0)
 98                 {
 99                     if(available > difference)
100                     {
101                         // 此时need数量不变 
102                         available -= difference;
103                     }
104                     else
105                     {
106                         need += difference - available; 
107                         available = 0;
108                     }
109                     
110                 }
111             }
112         }
113         
114         if(need < minNeed)
115         {
116             minNeed = need;
117             back = available;
118             path = tmp;
119         } else if(need == minNeed && available < back)
120         {
121             back = available;
122             path = tmp;
123         }
124         
125         // 顶点在dfs访问结束后弹出 
126         tmp.pop_back(); 
127         return;    
128     }
129     
130     for(int i = 0; i < pre[v].size(); ++i)
131         dfs(pre[v][i]);
132     
133     tmp.pop_back();        // 该顶点在dfs访问结束后弹出 
134 }
135 
136 int main()
137 {
138     scanf("%d%d%d%d", &C, &N, &Sp, &M);
139     for(int i = 1; i <= N; ++i)
140         scanf("%d", &s[i]);
141     
142     for(int i = 0; i <= N; ++i)
143     {
144         for(int j = 0; j <= N; ++j)
145         {
146             if(i == j)
147                 g[i][j] = 0;
148             else
149                 g[i][j] = INF;
150         }
151     }
152     
153     int a, b, cost;
154     for(int i = 0; i < M; ++i)
155     {
156         scanf("%d%d%d", &a, &b, &cost);
157         g[a][b] = g[b][a] = cost;
158     }
159     
160     dijkstra(0);
161     dfs(Sp);
162     
163     printf("%d 0", minNeed);
164     
165     int psize = path.size();
166     for(int i = psize-2; i >= 0; --i)
167     {
168         printf("->%d", path[i]);
169     }
170     
171     printf(" %d", back);
172 
173     return 0;
174 }

 

posted @ 2020-06-21 18:36  拾月凄辰  阅读(299)  评论(0编辑  收藏  举报