您的位置:首页 > 其它

[PAT]1018 Public Bike Management——Dijkstra+DFS

2019-02-21 23:16 363 查看

1018 Public Bike Management (30 分)

一、原题

There is a public bike service in Hangzhou City which provides great convenience to the tourists from all over the world. One may rent a bike at any station and return it to any other stations in the city.

The Public Bike Management Center (PBMC) keeps monitoring the real-time capacity of all the stations. A station is said to be in perfect condition if it is exactly half-full. If a station is full or empty, PBMC will collect or send bikes to adjust the condition of that station to perfect. And more, all the stations on the way will be adjusted as well.

When a problem station is reported, PBMC will always choose the shortest path to reach that station. If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.


The above figure illustrates an example. The stations are represented by vertices and the roads correspond to the edges. The number on an edge is the time taken to reach one end station from another. The number written inside a vertex S is the current number of bikes stored at S. Given that the maximum capacity of each station is 10. To solve the problem at S3, we have 2 different shortest paths:

1、PBMC -> S​1 -> S3. In this case, 4 bikes must be sent from PBMC, because we can collect 1 bike from S1 and then take 5 bikes to S3, so that both stations will be in perfect conditions.
2、PBMC -> S​2 -> S​3. This path requires the same time as path 1, but only 3 bikes sent from PBMC and hence is the one that will be chosen.

Input Specification:
Each input file contains one test case. For each case, the first line contains 4 numbers: Cmax (≤100), always an even number, is the maximum capacity of each station; N (≤500), the total number of stations; S​p, the index of the problem station (the stations are numbered from 1 to N, and PBMC is represented by the vertex 0); and M, the number of roads. The second line contains N non-negative numbers Ci (i=1,⋯,N) where each C​i is the current number of bikes at S​i respectively. Then M lines follow, each contains 3 numbers: S​i, S​j , and T​ij which describe the time T​ij taken to move betwen stations Si and S​j. All the numbers in a line are separated by a space.

Output Specification:
For each test case, print your results in one line. First output the number of bikes that PBMC must send. Then after one space, output the path in the format: 0−>S​1−>⋯−>S​p . Finally after another space, output the number of bikes that we must take back to PBMC after the condition of S​p is adjusted to perfect.

Note that if such a path is not unique, output the one that requires minimum number of bikes that we must take back to PBMC. The judge’s data guarantee that such a path is unique.

Sample 1 Input:

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

Sample1 Output:

3 0->2->3 0

Sample2 Input:

10 4 4 5
4 8 9 0
0 1 1
1 2 1
1 3 2
2 3 1
3 4 1

Sample2 Output:

1 0->1->2->3->4 2

二、题意:

1)给出SP,给出从PBMC到SP应该是携带自行车还是拿回自行车的最优方案。
2)如果最短路径有多条,那么选择从PMBC携带自行车最少的;如果仍有多条,就选从问题车站带回最少的方案。
3)沿途所有车站的调整过程必须在前往问题车站的过程中调整完毕,带回时不再调整。

三、分析:

1)对点权weight[]采用减去cmax/2的方法,即满足题意3);
2)对于是携带还是拿回,通过处理后的weight[]来判断即可。并且设置一个temppath[]来存储暂时最优路径,实现方式用递归从sp一直到PBMC,因此是先进入数组,后出数组。
3)本题不能只使用Dijkstra来解决,因为Minneed和MinBack在路径上传递不满足最优子结构。也就是当所有路径都确定后,才能去选择最小的need和最小的remain。**

四、AC代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;
const int maxv=510;
const int inf=100000000;
int d[maxv],g[maxv][maxv],weight[maxv];
int n,m,sp,cmax;
int minNeed=inf,minBack=inf;
bool vis[maxv]={false};
int numpath=0;
vector<int> pre[maxv];
vector<int> path,temppath;

void dijkstra(int s)
{
fill(d,d+maxv,inf);
d[s]=0;
for(int i=0;i<=n;i++)
{
int u=-1,mm=inf;
for(int j=0;j<=n;j++)
{
if(vis[j]==false && d[j]<mm)
{
mm=d[j];
u=j;
}
}
if(u==-1) return;
vis[u]=true;
for(int v=0;v<=n;v++)
{
if(vis[v]==false && g[u][v]!=inf)
{
if(d[u]+g[u][v]<d[v]){
d[v]=g[u][v]+d[u];
pre[v].clear();
pre[v].push_back(u);
}
else if(d[u]+g[u][v]==d[v]) pre[v].push_back(u);
}
}
}
}
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 > (0 - weight[id])) {
// 如果back中是足够的,先从back中扣出
back += weight[id];
} else {
// 如果back不够,那么需要从need中借
need += ((0 - weight[id]) - back);
back = 0;
}
}
}
//计算最小的需求
if(need < minNeed) {
minNeed = need;
minBack = back;
path = temppath;
//计算最小需求中带回来最少的
} else if(need == minNeed && back < minBack) {
minBack = back;
path = temppath;
}
// 顶点在dfs访问结束后弹出
temppath.pop_back();
return ;
}
for(int i=0;i<pre[v].size();i++)
{
dfs(pre[v][i]);
}
temppath.pop_back();
}
int main()
{
scanf("%d %d %d %d",&cmax,&n,&sp,&m);
int u,v;
fill(g[0],g[0]+maxv*maxv,inf);
for(int i=1;i<=n;i++)
{
scanf("%d",&weight[i]);
weight[i]-=cmax/2;
}
for(int i=0;i<m;i++)
{
scanf("%d %d",&u,&v);
scanf("%d",&g[u][v]);
g[v][u]=g[u][v];
}

dijkstra(0);
dfs(sp);
printf("%d ",minNeed);
for(int i=path.size()-1;i>=0;i--){
printf("%d",path[i]);
if(i>0) printf("->");
}
printf("% d\n",minBack);
return 0;
}

五、小结

1、此题和PAT1030 Travel Plan是一个类型。
2、此题难点,1)点权可能有多种情况,因此采用DFS处理;2)最优路径,有第二、三标准,因此采用DFS与path、temppath两个数组来筛选,3)路径的输出采用pre[]来存入每个结点的前驱,便于DFS中从SP结点回溯到PBMC。
3、此题有n+1个结点,调试了多次都没注意PBMC是0号店,循环中漏了‘=’,花了不少时间。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: