这道题的建图,比较有讲究,开始想了很久,到底是怎么建图能体现现出换电梯需要六十秒!后来参考了别人的思路,就是只要一条边走到头,就换电梯,也就是换边就是换电梯。
建图,把每个电梯能到达的楼层,两两之间有一条边,如果有其他电梯的这条边更短,选择更短的。
每次换边的时候,要注意加60,因为需要60秒;最后结构要-60,因为第一次进电梯不需要60;如果去第0层,就是另外处理,是0,否则正常输出的是-60
代码:
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 110;
const int INF = 10000000;
int n, k, cnt;
int g[N][N], d[N], t[10], tmp[N];
bool vis[N];
void build( int ss ) {
for ( int i = 0; i < cnt; ++i )
for ( int j = i + 1; j < cnt; ++j ) {
int dist = abs( tmp[j] - tmp[i] ) * t[ss], x = tmp[i], y = tmp[j];
if ( dist < g[x][y] ) g[x][y] = g[y][x] = dist;
}
}
int dij( ) {
memset( vis, 0, sizeof(vis));
d[0] = 0;
for ( int u = 0; u < 100; ++u ) {
int mi = INF, v;
for ( int i = 0; i < 100; ++i ) if ( !vis[i] && mi > d[i] ) mi = d[i], v = i;
vis[v] = 1;
for ( int i = 0; i < 100; ++i ) if ( !vis[i] && d[i] > d[v] + g[v][i] +60 ) d[i] = d[v] + g[v][i] + 60;
}
return d[k];
}
int main()
{
while ( scanf("%d%d", &n, &k) != EOF ) {
for ( int i = 0; i < n; ++i ) scanf("%d", &t[i]);
for ( int i = 0; i < N; d[i] = INF, ++i ) for ( int j = 0; j < N; ++j ) g[i][j] = INF;
for ( int i = 0; i < n; ++i ) {
char ch;
cnt = 0;
while ( 1 ) {
scanf("%d%c", &tmp[cnt++], &ch);
if ( ch == 0xa ) break;
}
build( i );
}
int ans = dij();
if ( ans == INF ) printf("IMPOSSIBLE\n");
else printf("%d\n", k == 0 ? 0 : ans-60);
}
}