1018. Public Bike Management (30)
看到题目后感觉挺麻烦的,参考了别人的代码,找到了思路。
首先是题目要求:最短路径,拿出最少,拿回最少
解题思路:用dijkstra找到0到其他点的最短路径dis[k],在dfs的时候用来剪枝。
到达sp时候处理tpath存下的最短路径,找到一路上最大需求数量need作为0点拿出的数量
need+sp还有的数量get 就是 拿回的数量back。将答案存入path中
最后要用visit来记录并回溯所有情况
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=502,inf=1e9;
int a[N],mp[N][N],dis[N],used[N],visit[N],path[N],tpath[N],plen;
int cmax,n,sp,m,needMin=inf,backMin=inf;
void input(){
scanf("%d %d %d %d",&cmax,&n,&sp,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]=a[i]-cmax/2;//多余
}
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
mp[i][j]=inf;
for(int i=0,u,v,w;i<m;i++){
scanf("%d %d %d",&u,&v,&w);
mp[u][v]=w,mp[v][u]=w;
}
}
void Dijkstra(){
int k;
for(int i=1;i<=n;i++)
dis[i]=mp[0][i];
for(int i=1;i<=n;i++){
int tmin=inf;
for(int j=1;j<=n;j++)
if(!used[j]&&tmin>dis[j])
tmin=dis[j],k=j;
used[k]=1;
for(int j=1;j<=n;j++)
if(dis[k]+mp[k][j]<dis[j])
dis[j]=dis[k]+mp[k][j];
}
}
void dfs(int x,int dist,int len){
if(dist>dis[x]) return;//剪枝
if(x==sp){
int need=0,get=0;
for(int i=0;i<len;i++){
get+=a[tpath[i]];
if(-get>need)
need=-get;
}
int back=need+get;
if(need<needMin||(need==needMin&&back<backMin)){
needMin=need,backMin=back;
for(int i=0;i<len;i++)
path[i]=tpath[i];
plen=len;
}
return;
}
for(int i=1;i<=n;i++){//回溯
if(!visit[i]&&mp[x][i]!=inf){
visit[i]=1;
tpath[len]=i;
dfs(i,dist+mp[x][i],len+1);
visit[i]=0;
}
}
}
void print(){
printf("%d %d",needMin,0);
for(int i=0;i<plen;i++)
printf("->%d",path[i]);
printf(" %d\n",backMin);
}
int main(){
input();
Dijkstra();
dfs(0,0,0);
print();
return 0;
}