题目:pat—1018、Public Bike Management
题目思路:
先用Dijkstra算出多条最短路径,并用vector<int> pre[n+1]存路径,再用DFS的方法遍历一遍路径,进行筛选。
代码展示:
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int maxn=1e3+5;
int p,n,endx,m,inf=999999999;
int cur[maxn],d[maxn],e[maxn][maxn];
bool vis[maxn+1];
vector <int> pre[maxn+1];
int minback=inf,mintake=inf,ans[maxn],tmp[maxn];
void init() { //初始化
cin>>p>>n>>endx>>m;
p/=2;
memset(vis,false,sizeof(vis));
cur[0]=0;
for (int i=1; i<=n; i++) {
pre[i].push_back(0);
cin>>cur[i];
}
for (int i=0; i<=n; i++)
for (int j=0; j<=n; j++) {
if (i==j) e[i][j]=0;
else e[i][j]=inf;
}
for (int i=1; i<=m; i++) {
int v1,v2,val;
cin>>v1>>v2>>val;
e[v1][v2]=val;
e[v2][v1]=val;
}
}
void Dijkstra() { //最短路径
vis[0]=true;
for (int i=0; i<=n; i++) d[i]=e[0][i]; //初始化距离
for (int i=1; i<=n; i++) {
int u,mind=inf;
for (int j=0; j<=n; j++) if (!vis[j] && d[j]<mind ) {
mind=d[j];
u=j;
}
vis[u]=true;
for (int v=0; v<=n; v++) if (u!=v && e[u][v]<inf ) {
if (d[v]>d[u]+e[u][v]) {
d[v]=d[u]+e[u][v];
pre[v].clear();
pre[v].push_back(u);
} else if ( d[v]==(d[u]+e[u][v]) ) {
pre[v].push_back(u);
}
}
}
}
void Dfs(int endx,int step){ //在已经求出的多条最短路径中筛选出最优的一条,分别以take(带过去的自行车数量)和back(带回来的数量)作为第一、第二标准
tmp[step]=endx;
if (endx==0) {
int sum=0,take=0;
for (int i=step-1;i>=1;i--){
if (sum+cur[tmp[i]]<p) {
take+=(p-sum-cur[tmp[i]]);
sum=0;
}
else sum=cur[tmp[i]]+sum-p;
}
if (take<mintake){
mintake=take;
minback=sum;
for (int i=step;i>=1;i--) ans[i]=tmp[i];
ans[0]=step;
}else if (take==mintake && sum<minback){
mintake=take;
minback=sum;
for (int i=step;i>=1;i--) ans[i]=tmp[i];
ans[0]=step;
}
return;
}
for (int i=0;i<pre[endx].size();i++){
Dfs(pre[endx][i],step+1);
}
}
int main() {
// freopen("datain.txt","r",stdin);
init();
Dijkstra();
Dfs(endx,1);
cout<<mintake<<" 0";
for (int i=ans[0]-1;i>=1;i--) cout<<"->"<<ans[i];
cout<<" "<<minback<<endl;
}