PAT.A1018 Public Bike Management

返回目录在这里插入图片描述

在这里插入图片描述

题意

城市里有一些公共自行车站, 每个车站的自行车最大容量为一个偶数Cmax,且如果一个车站中自行车的数量恰好为Cmax/2,那么称该车站处于“完美状态”。而如果一个车站容量是满的或是空的,那么控制中心(PBMC)就会携带或从路上收集一定数量的自行车前往该车站,以使问题车站及沿途所有车站都达到“完美状态”。现在给出Cmax、车站数目N (不含控制中心PBMC)、问题车站编号Sp、无向边数M及边权,求一条从PBMC (记为0号)到达问题车站Sp的最短路径,输出需要从PBMC携带的自行车数目、最短路径、到达问题车站后需要带回的自行车数目。如果最短路径有多条,那么选择从PBMC携带的自行车数目最少的:如果仍然有多条,那么选择最后从问题车站带回的自行车数目最少的。注意:沿途所有车站的调整过程必须在前往问题车站的过程中就调整完毕,带回时不再调整。

样例(可复制)

10 3 3 5
6 7 0
0 1 1
0 2 1
0 3 3
1 3 1
2 3 1
//output
3 0->2->3 0

注意点

  1. 本题解题思路为Djikstra+DFS。具体为:先用Dijkstra找到最短路径,找的过程中,记录下每个路径的每个节点的前驱节点。使用DFS从问题站点出发,利用刚才记录下的前驱节点返回到PBMC,把路径记下,再从PBMC出发计算需要带的单车数量need和需要取回的单车数量remain,与minneed和minremain进行比较,更新最短路径。
#include<bits/stdc++.h>
using namespace std;

int Cmax,n,sp,m,minneed=INT_MAX,minremain=INT_MAX;//Cmax为最大容量,n为顶点数,sp为问题站点,m为边数
int G[510][510],weight[510],dis[510];//G为图,weight为车站单车数量,dis为到某节点的距离
bool vis[510]={false};//标记是否访问过该节点
vector<int> temp,path,pre[510];//temp为临时路径,path为最短路径,pre存储前驱节点
void Dijkstra(){
	fill(dis,dis+n+1,INT_MAX); //注意第二个参数为dis+n+1
	dis[0]=0;
	while(!vis[sp]){
		int v,minn=INT_MAX;
		for(int i=0;i<=n;i++){
			if(!vis[i]&&dis[i]<minn){
				minn=dis[i];
				v=i;
			}
		}	
		vis[v]=true;
		for(int i=0;i<=n;i++){
			if(!vis[i]&&G[v][i]!=0&&dis[i]>dis[v]+G[v][i]){
				dis[i]=dis[v]+G[v][i];
				pre[i].clear();
				pre[i].push_back(v);
			}else if(!vis[i]&&G[v][i]!=0&&dis[i]==dis[v]+G[v][i]){
				pre[i].push_back(v);
			}
		}
	}
}
void DFS(int v){
    temp.push_back(v);
	if(v==0){
		int need=0,remain=0;
		for(int i=temp.size()-1;i>=0;i--){//注意从后往前才是从PBMC出发到问题站点的路径
			int now=temp[i];
			if(weight[now]>=0){
				remain+=weight[now];
			}else{
				if(remain>abs(weight[now])){
					remain+=weight[now];
				}else{
					need+=abs(weight[now])-remain;
					remain=0;
				}
			}
		}
		if(need<minneed){
			path=temp;
			minneed=need;
			minremain=remain;
		}else if(need==minneed&&remain<minremain){
			path=temp;
			minneed=need;
			minremain=remain;
		}
		temp.pop_back();
		return;
	}
	for(int i=0;i<pre[v].size();i++)DFS(pre[v][i]);
	temp.pop_back();
}
int main(){
	cin>>Cmax>>n>>sp>>m;
	for(int i=1;i<=n;i++){
		scanf("%d",&weight[i]);
		weight[i]-=Cmax/2; 
	} 
	int u,v,w;
	while(m--){
		scanf("%d%d%d",&u,&v,&w);
		G[u][v]=G[v][u]=w;
	}
	Dijkstra();
	DFS(sp);
	printf("%d ",minneed);
	for(int i=path.size()-1;i>=0;i--){
		printf("%d",path[i]);
		if(i>0)printf("->");
	}
	printf(" %d",minremain);
    return 0;
}
发布了177 篇原创文章 · 获赞 5 · 访问量 6652

猜你喜欢

转载自blog.csdn.net/a1920993165/article/details/105567424