提交情况:
代码:
#include <iostream> #include <string.h> #include <vector> #include <math.h> using namespace std; #define Max 501 #define INF 0x3f3f3f3f int Cmax,n,sp,m; int visit[Max],dist[Max],weight[Max],w[Max]; int Graph[Max][Max]; vector<int> pre[Max],temp,path; int minNeed = INF,minRemain = INF; void Dijkstra ( int start ) //找到最短路径并存储最短路径 { visit[start] = 1; for( int i=0; i<=n; ++i) { int vertex = -1,min = INF; for( int j=0;j<=n;++j) //找到边权最小 { if( visit[j] == 0 && dist[j] < min ) { vertex = j; min = dist[j]; } } visit[vertex] = 1; for( int j=0;j<=n;++j) { if( visit[j] == 0 ) { if( dist[vertex] + Graph[vertex][j] < dist[j] ) //找到了更短的路径 { dist[j] = dist[vertex] + Graph[vertex][j]; //记录最短路径长度 pre[j].clear(); pre[j].push_back(vertex); //把最短路径上该节点的前驱节点记录下来 } else if( dist[vertex] + Graph[vertex][j] == dist[j] ) //最短路径相同 { pre[j].push_back(vertex); //如果有相同的最短路径,则把该前驱节点也记录下来 } } } } } void DFS( int start ) { if( start == 0) { temp.push_back(start); int need = 0,remain = 0; //need为当前车站需要补充的,remain为当前车站后剩余的 // cout<<"temp length:"<<temp.size()<<endl; for( int i = temp.size()-1;i>=0;--i) { // cout<<"节点为:"<<temp[i]<<endl; if( weight[temp[i]] > 0 ) //如果该车站有盈余,则将剩余的自行车数量加上该盈余 { remain = remain + weight[temp[i]]; } else //如果当前车站不足(weight[i]<=0) { if( remain > abs(weight[temp[i]]) ) //如果剩余的自行车数量大于所缺少的 { remain = remain - abs(weight[temp[i]]); } else //remain <= abs(weight[i]) { need += abs(weight[temp[i]]) - remain; remain = 0; } } } // cout<<need<<"***"<<remain<<endl; if( need < minNeed ) //需要从PBMC带的自行车数量更少 { minNeed = need; minRemain = remain; path = temp; } else if( need == minNeed && remain < minRemain ) //如果从PBMC带的自行车相同, { // 那么选择从问题车站带回最少的 minRemain = remain; path = temp; } temp.pop_back(); return ; } temp.push_back(start); for( int i=0;i<pre[start].size();++i ) { DFS(pre[start][i]); } temp.pop_back(); } int main () { cin>>Cmax>>n>>sp>>m; int pbmc = 0; for( int i=1;i<=n;++i ) { cin>>weight[i]; weight[i] = weight[i] - Cmax/2; memset(Graph[i],INF,sizeof(Graph[i])); } memset(Graph[0],INF,sizeof(Graph[0])); for( int i=1;i<=m;++i ) { int a,b; cin>>a>>b; cin>>Graph[a][b]; Graph[b][a] = Graph[a][b]; } //初始化 for( int i=0; i<=n; ++i) { if( Graph[pbmc][i] != INF ) { dist[i] = Graph[pbmc][i]; w[i] = weight[i]; pre[i].push_back(pbmc); } else dist[i] = INF; } Dijkstra(pbmc); // for( int i=0;i<=n;++i ) //查看最短路径上的前驱 // { // cout<<"第"<<i<<"节点的前驱:"; // for( int j=0;j<pre[i].size();++j ) // { // if( j == pre[i].size()-1 ) // cout<<pre[i][j]<<endl; // else // cout<<pre[i][j]<<" "; // } // } // for( int i=0;i<=n;++i ) //查看weight数组 // { // if( i == n) // cout<<weight[i]<<endl; // else // cout<<weight[i]<<" "; // } // for( int i=0;i<=n;++i ) //查看dist数组 // { // if( i == n) // cout<<dist[i]<<endl; // else // cout<<dist[i]<<" "; // } DFS(sp); //从问题车站开始。该DFS算法并不是纯粹的深度优先算法。利用DFS遍历到达sp的最短路径 cout<<minNeed<<" "; for( int i = path.size()-1;i>=0;--i ) { if( i == 0 ) cout<<path[i]<<" "; else cout<<path[i]<<"->"; } cout<<minRemain<<endl; return 0; }这道题还是挺不错的,我不会做,看了算法笔记之后才明白的。 算法思想:利用Dijkstar求出最短路径,但是并不是只求最短的长度,还记录下最短路径上某一个节点的前驱节点,如果有相同的最短路径,那么同时也记录下来,放在某一个数组中。而后利用DFS算法,从问题车站开始,依次遍历到达问题车站的最短路径,在遍历过程统计需要的自行车和剩余的自行车。