点击打开链接uva 10801
思路:最短路+Dijkstra
分析:
1 有n个电梯,电梯可以到达的层数是一定的,那么我们就把楼层看成是图上的点,那么我们就可以得到的哪些点是有连通的。
2 又由于有多个电梯,所以x->y可能有多种方式,所以这就类似于重边问题那么我们要选择边权值最小的最为最后的边权值。
3 接下来图建好以后就是考虑怎么Dijkstra,由于要交换乘坐电梯,那么我们就自然的想到了图论中的换边(松弛步),那么我们就把换乘电梯看成是在换边,就是说只要做松弛步就是在换成电梯,那么这个时候就要加上等电梯的时间60s。
4 这里有个地方就是由于源点是会做松弛步的,但是源点是不用加上60s的,所以最后输出的时候要特判一下。如果k为0,直接输出0;如果k部位0,那么最后的输出要减去60.
代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; #define MAXN 110 #define INF 0xFFFFFFF int n , k , pos; int value[MAXN][MAXN]; int t[6]; int dis[MAXN]; int vis[MAXN]; int num[10010]; /*初始化变量*/ void init(){ memset(t , 0 , sizeof(t)); memset(vis , 0 , sizeof(vis)); dis[0] = 0; for(int i = 1 ; i < 100 ; i++) dis[i] = INF; for(int i = 0 ; i <100 ; i++){ for(int j = 0 ; j < 100 ; j++) value[i][j] = INF; } } /*建立无向图*/ void build_Grap(int x){ for(int i = 0 ; i < pos; i++){ for(int j = i ; j < pos ; j++){ int tmp = abs(num[j]-num[i])*t[x]; if(value[num[i]][num[j]] > (abs(num[i]-num[j]))*t[x]) value[num[i]][num[j]] = value[num[j]][num[i]] = tmp; } } } /*Dijkstra算法*/ void Dijkstra(){ for(int i = 0 ; i < 100 ; i++){ pos = -1; for(int j = 0 ; j < 100 ; j++){ if(!vis[j] && (pos == -1 || dis[j] < dis[pos])) pos = j; } vis[pos] = 1; for(int j = 0 ; j < 100 ; j++){ if(!vis[j]){ if(dis[j] > dis[pos] + value[pos][j] + 60)/*这里注意一下要加上60*/ dis[j] = dis[pos] + value[pos][j] + 60; } } } /*输出特判*/ if(dis[k] != INF){ if(k) printf("%d\n" , dis[k]-60); else printf("0\n"); } else printf("IMPOSSIBLE\n"); } int main(){ //freopen("input.txt" , "r" , stdin); int tmp; char ch; while(scanf("%d%d" , &n , &k) != EOF){ init(); for(int i = 1 ; i <= n ; i++) scanf("%d" , &t[i]); for(int i = 1 ; i <= n ; i++){ memset(num , 0 , sizeof(num)); pos = 0; /*输入问题用getchar()来判断*/ do{ scanf("%d" , &num[pos++]); }while(getchar() != '\n'); build_Grap(i); } Dijkstra(); } return 0; }