UVa 10801 Lifting Hopping (Dijsltra)

这道题的建图,比较有讲究,开始想了很久,到底是怎么建图能体现现出换电梯需要六十秒!后来参考了别人的思路,就是只要一条边走到头,就换电梯,也就是换边就是换电梯。

建图,把每个电梯能到达的楼层,两两之间有一条边,如果有其他电梯的这条边更短,选择更短的。

每次换边的时候,要注意加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);
    }
}



你可能感兴趣的:(UVa 10801 Lifting Hopping (Dijsltra))