其实还是个最短路的问题,但是建图略微麻烦。同一个电梯里相邻停留的楼层之间连边,有多个电梯停留的同一楼层之间连边。比较麻烦,我们可以从边的角度出发因此使用Bellmanford算法。这样求最短路就需要开一个二维数组,用1维表示电梯另1维表示楼层。
核心是dist[T][to]>dist[F][from]+w。
另外就是注意读取可以停留的楼层要用字符串读。dist[][]要将可以在0层停留的电梯初始化为0,其余为无穷大以表示不可到达。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; struct Edge { int A,B,a,b,weight; void set(int AA,int BB,int aa,int bb,int cc) { A=AA; B=BB; a=aa; b=bb; weight=cc; } }; int main() { int n,K; while(scanf("%d%d",&n,&K)!=EOF) { int t[6]= {0}; for(int i=0; i<n; ++i) scanf("%d",&t[i]); getchar(); Edge p[10000]; int N=0; bool have[6][105]= {0}; for(int i=0; i<n; ++i) { char c; int num=0,fro=-1; while(scanf("%c",&c)) { if(isdigit(c)) num=num*10+c-'0'; else { for(int k=0; k<n; ++k) if(have[k][num]) { p[N++].set(i,k,num,num,60); p[N++].set(k,i,num,num,60); } have[i][num]=true; if(fro!=-1) { p[N++].set(i,i,fro,num,(num-fro)*t[i]); p[N++].set(i,i,num,fro,(num-fro)*t[i]); } fro=num; num=0; } if(c=='\n') break; } } int dist[6][105]; memset(dist,0x7f,sizeof(dist)); int INF=dist[0][0]; for(int i=0; i<n; ++i) if(have[i][0]) dist[i][0]=0; while(1) { bool update=false; for(int i=0; i<N; ++i) { int &from=p[i].a,&to=p[i].b,&F=p[i].A,&T=p[i].B,&w=p[i].weight; if(dist[F][from]!=INF&&dist[T][to]>dist[F][from]+w) { dist[T][to]=dist[F][from]+w; update=true; } } if(!update) break; } int ans=INF; for(int i=0; i<n; ++i) ans=min(dist[i][K],ans); if(ans==INF)puts("IMPOSSIBLE"); else printf("%d\n",ans); } return 0; }