题意:(非原创)
有一层不超过100层的大楼, 有n个电梯,它们的速度都不同。 而且每个电梯只能到达指定的那些楼层,而且它们都有各自的速度(即上升一层或下降一层所用的时间)。 如果一个人在某层走出电梯,要换一个电梯乘,那么他要等60秒(不管要等的是那个电梯,即使是刚刚出来的那个电梯也要等60秒)。在0层搭电梯出发时不需要等待。
一个人从0层开始,目的地是k层, 现在要搭这些电梯,问最少需多少时间
思路:
实际上就是求最小路,然后每次转换电梯的时候就加60
Dijkstra其实和prim很像,不一样的就是在每次纳入一个点之后是调整每个点到原点的距离
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
const int N = 105;
const int INF = 0x3f3f3f3f;
int g[N][N];
int d[N];
int vis[N], num[N];
int n, aid, cnt, tim[N];
void add(int t, int d, int s) {
int dis = abs(t-d)*s;
if(g[d][t] > dis)
g[d][t] = g[t][d] = dis;
}
void init() {
for(int i=0; i<n; i++)
scanf("%d", &tim[i]);
memset(g, INF, sizeof(g));
memset(d, INF, sizeof(d));
d[0] = 0;
char ch;
for(int i=0; i<n; i++) {
ch = '\0';
for(int j=0; ch != '\n'; j++) {
scanf("%d%c", &num[j], &ch);
for(int k = 0; k<j; k++) {
add(num[j], num[k], tim[i]);
}
}
}
}
void deal() {
memset(vis, 0, sizeof(vis));
for(int i=0; i<99; i++) {
int x, flag=0, m = INF;
for(int j=0; j<100; j++) {
if(!vis[j] && d[j]<m) {
m = d[j];
flag = 1;
x = j;
}
}
if(!flag) return;
vis[x] = 1;
for(int j=0; j<100; j++) {
if(!vis[j] && d[j]>d[x]+g[x][j]+60)
d[j] = d[x] + g[x][j] + 60;
}
}
}
int main() {
while(scanf("%d%d", &n, &aid) != EOF) {
init();
deal();
if(aid == 0) printf("0\n");
else if(d[aid] != INF) printf("%d\n", d[aid]-60);
else printf("IMPOSSIBLE\n");
}
return 0;
}