题目
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
思路
总体思路没有很难想
- 先找出所有从 S 0 S_0 S0到 S p S_p Sp的最短路径。
- 再从这些路径中选出一条路径,它所需要从 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;
}