PAT甲1018 Public Bike Management Bike Management 两点间所有最短路径/深度优先dfs/优先级的坑

题目

题目

Input Sample

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

Output Sample

3 0->2->3 0

思路

总体思路没有很难想

  1. 先找出所有从 S 0 S_0 S0 S p S_p Sp的最短路径。
  2. 再从这些路径中选出一条路径,它所需要从 S 0 S_0 S0带出的自行车数send最小。坑点来了! 若send相同,则选择从 S p S_p Sp带回的自行车数take最小(最后3个测试点应该都是这个问题)

算法

针对思路中第1步,可以用深度优先搜索dfs的思想,过程中记录下路径信息
针对思路中第2步,在遍历每条最短路径上的点时,维护两个变量:从 S 0 S_0 S0点带出的自行车数send,和沿途手中拥有的自行车数inhand。到达终点后需要带回的自行车数就是这时的inhand

AC代码

#include <iostream>
#include <vector> 
using namespace std;
int dest;   //index of destination
int start;  //index of start
int Cmax,N,Sp,M;
int c[501];
int Adj[501][501];  		//Adjacency matrix
int minLen = 9999999; 		//length of shortest path
int nextStep[1000]; 		//next step of index i
vector<vector<int> > paths; //shortest paths
bool mark[501];				//unvisited or visited 
vector<int> path;			//a temp shortest path
/*
* find all the shortest paths
* @param curr: current index
* @param len: length of the current path
*/
void dfs(int curr,int len){
	
	if(curr == dest){
		if(len<minLen){
			minLen = len;
			paths.clear();
		}
		if(len==minLen){
			//write down a shortest path 
			path.clear();
			int p = start;
			while(p!=dest){
				path.push_back(p);
				p = nextStep[p];
			}
			path.push_back(dest);
			paths.push_back(path);
		}
		return;
	}
	
	for(int i = 1;i<=N;++i){
		if(Adj[curr][i]!=0 && mark[i] == false){
			mark[i] = true;
			nextStep[curr] = i;
			dfs(i,len+Adj[curr][i]);
			mark[i] = false;  //!!!
		}
	}
	return;
}
int main() {
	
	cin>>Cmax>>N>>Sp>>M;
	//Input number of bikes 
	for(int i = 1;i<=N;++i){
		cin>>c[i];
	}
	//Input road information
	for(int i = 1;i<=M;++i){
		int v1,v2,t;
		cin>>v1>>v2>>t;
		Adj[v1][v2] = Adj[v2][v1] = t; 
	}
	//shortest paths from S0 to Sp
	dest = Sp;
	start = 0;
	dfs(0,0);
	//choose the best path
	int perfect = Cmax/2;
	int inhand = 0, send = 0;
	int minSend = 9999999,minTake = 9999999;
	vector<vector<int> >::iterator minIt;
	for(vector<vector<int> >::iterator it = paths.begin(); it != paths.end(); ++it){
		inhand = send = 0;
		for(vector<int>::iterator iit = (*it).begin()+1; iit !=(*it).end(); ++iit){
			if(c[(*iit)] < perfect && perfect - c[(*iit)] > inhand){
				send += perfect - c[(*iit)] - inhand;
				inhand = 0;
			}else if(c[(*iit)] < perfect && perfect - c[(*iit)] <= inhand){
				inhand -= perfect - c[(*iit)];
			}else if(c[(*iit)] > perfect){
				inhand += c[(*iit)] - perfect;
			}
		}
		if(minSend > send || minSend == send && minTake > inhand){
			minSend = send;
			minTake = inhand;
			minIt = it;
		}
	}
	//Output	
	cout<<minSend<<" "<<start;
	for(vector<int>::iterator iit = (*minIt).begin()+1;iit!=(*minIt).end();++iit){
		cout<<"->"<<(*iit);
	}
	cout<<" "<<minTake;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值