PAT 1018. Public Bike Management (30)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hit_shaoqi/article/details/81144839

题目:自行车管理,从根结点出发,或者是带回自行车,或者是带着自行车去,一路上逐一平衡结点的自行车数量,知道最终的结点;要求找出最短路径,如果多条最短路径,就找最短路径中需要带的自行车的数量最少的

原理:

1. 建立邻接矩阵,这个矩阵,从根节点出发,遍历邻接矩阵,得到距离想要更新的结点的最短路径,这个路径也是存在一个vector中,vector类型的数组,vector数组中的元素表示当前结点的各个前驱结点,因此最终的到的vector数组就是多条最短路径。使用dijkstra算法;

这时候已经得到距离目标节点的最短路径了

2. 使用深度优先,从目标节点递归找,直到找到根节点,深度递归中每次到达根节点,都根据对对自行车的数量,选择是否当前的路径,最终就得到了即最短,又最少需求的路径。

代码:

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

using namespace std;
const int maxv = 505,INF = 0x3f3f3f3f;
int cost[maxv][maxv];
int dist[maxv];
bool visited[maxv];
vector<int> pre[maxv];//记录最短路径上每个结点的前驱结点

int Cmax,dest,n,m;
 
void init()
{
	for(int i=0;i<n;++i){
		for(int j=0;j<n;j++) 
		{
			if(i==j)
				cost[i][j] = 0;
			else
				cost[i][j] = INF;
		}
	} 
	memset(visited, false,sizeof(visited))
} 

void dijkstra(int v0) // dijkstrra 最短路径算法
{
	for(int i=0;i<=n;++i){
		dist[i] = cost[v0][i];
		if(dist[i] ==INF)
			pre[i].clear();
		else
			pre[i].push_back(v0);
	} 
	visited[v0]=true;
	
	for(int i=0;i<n;++i){
		int min_dist = INF,Pos;
		for(int j=0;j<=n;++j){//找出距离v0结点最近的结点pos,并记录举例 
			if(!visited[j]&&dist[j]<min_dist){
				pos = j;
				min_dist = dist[j];
			}
		}
		visited[pos] = true;
		for(int j=0;j<=n;++j){
			if(!visited[j] && dist[pos]++cost[pos][j]<dist[j]){
				dist[j] = dist[pos]+cost[pos][j];
				pre[j].clear();
				pre[j].push_back(pos);
			} 
			else if(!visited[j]&&dist[post]+cost[post][j]==dist[j]){
				pre[j].push_back(pos);
			}	
		}
	}
	return;
} 

int diff[maxv];
vector <int> tmpPath,resPath;
int minExtra = INF,minNeed = INF;

void DFS(int v){
	if(v==0){
		tmpPath.push_back(v);//DFS选择
		int need = 0,extra = 0;
		for(int i=tmpPath.size()-1;i>=0;--i){
			int id = tmpPath[i];
			if(diff[id]>0)
				extra +=diff[id];
			else if(diff[id]<0){
				if(extra>(-diff[id]))
					extra +=diff[id];
				else{
					need +=(-diff[id]-extra);
					extra = 0;
				}
			}
		}
		if(need < minNeed){
			minNeed = need;
			minExtra = extra;
			resPath = tmpPath; 
		}
		else if(need== minNeed && extra<minExtra){
			minExtra = extra;
			resPath  = tmpPath; 
		}
		tmpPath.pop_back();
		return;
	}
	//通过v 
	tmpPath.push_back(v);
	//遍历v的前驱结点 
	for(int i=0;i<pre[v].size();++i)
		DFS(pre[v][i]);
	//不通过v
	tmpPath.pop_back();
	return; 
}


 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {
	cin>>Cmax>>n>>dest>>m;
	diff[0]=0;
	for(int i=1;i<=n;++i){
		cin>>diff[i];
		diff[i]-=Cmax>>1; 
	}
	
	inst st,ed,c;
	init();
	for(int i=0;i<m;++i)
	{
		cin>>st>>ed>>c;
		cost[st][ed]=cost[ed][st]=c;
	}
	dijkstra(0);
	DFS(dest);
	cout<<minNeed;
	for(int i = resPath.size()-1;i>=0;--i){
		if(i==resPath.size()-1)
			cout <<' ';
		else
			cout << "->";
		cout <<resPath[i];
	}
	
	cout <<' '<<minExtra<<endl;
	
	return 0;

}

猜你喜欢

转载自blog.csdn.net/hit_shaoqi/article/details/81144839