POJ 1135 Domino Effect(最短路径+枚举)

题目大意:

多米诺骨牌游戏:给出一些关键骨牌(1~n),关键骨牌中间有一些普通骨牌,每个骨牌倒下的时间都是1 seconds,推到第一个关键骨牌,问最后一个骨牌倒下的时间和位置(可以是关键骨牌,或者是普通骨牌)。

解题思路:

本题并不难,关键是读懂题。本题可抽象成一个带权无向图,关键骨牌为带权无向图的结点,关键骨牌中间的普通骨牌数量抽象成带权边。当一个关键骨牌倒下时,之后和其有关联的普通骨牌倒下,当一个普通骨牌倒下时,之后在其后面的骨牌会倒下。使用dijkstra算法计算出当推到第一个关键骨牌后,其他关键骨牌倒下的时间lowc[i],选择一个最大时间max1(max1=max{lowc[i]|0<i<n &&}); 有可能会是普通骨牌倒下,关键骨牌之间的普通骨牌倒下的时间为:(lowc[i] + lowc[j] + 关键骨牌间的普通骨牌数目)/2,选择一个最大的时间max2,比较max1和max2的值。

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define INF 0x3f3f3f3f
#define eps 1e-6
#define M 1000
using namespace std;

struct Edge{
    int x;
    int y;
    int l;
}edge[M*M];

int n, m;
int a, b, l;

int vis[M], lowc[M], dis[M][M];

void dijkstra(int v) {
    int i, j;
    for(i=0; i<n; i++) {
        lowc[i] = dis[v][i];
        vis[i] = 0;
    }
    vis[v] = 1;
    int minc, u;
    for(i=1; i<n; i++) {
        minc = INF; u = -1;
        for(j=0; j<n; j++) {
            if(vis[j] == 0 && lowc[j] < minc) {
                minc = lowc[j]; u = j;
            }
        }
        vis[u] = 1;
        for(j=0; j<n; j++) {
            if(vis[j] == 0 && lowc[j] > lowc[u] + dis[u][j]) {
                lowc[j] = lowc[u] + dis[u][j];
            }
        }
    }
    return ;
}

int main() {
    int i, j, k;
    int c = 1;
    while(scanf("%d%d", &n, &m)) {
        if(n == 0 && m == 0) break;
        for(i=0; i<n; i++) {
            for(j=0; j<n; j++) {
                if(i == j) dis[i][j] = 0;
                else dis[i][j] = INF;
            }
        }
        for(i=0; i<m; i++) {
            scanf("%d%d%d", &a, &b, &l);
            dis[a-1][b-1] = l; dis[b-1][a-1] = l;
            edge[i]. x = a-1; edge[i].y = b-1;
            edge[i].l = l;
        }
        dijkstra(0);
        int max1_x = 0, max1 = 0;          //关键骨牌倒下的时间和序号
        for(i=0; i<n; i++) {
            if(lowc[i] > max1) {
                max1 = lowc[i];
                max1_x = i;
            }
        }
        int max2_x, max2_y;                 //普通骨牌倒下的时间和两端的关键骨牌
        double max2 = -1.0;
        for(i=0; i<m; i++) {
            double tmp = (lowc[edge[i].x] + lowc[edge[i].y] + edge[i].l) * 1.0 / 2;
            if(tmp - max2 > eps) {
                max2 = tmp;
                max2_x = edge[i].x;
                max2_y = edge[i].y;
            }
        }
        printf("System #%d\n", c ++);
        if(max1*1.0 - max2 < 0) {
            printf("The last domino falls after %.1f seconds, between key dominoes %d and %d.\n\n",
                   max2, min(max2_x + 1, max2_y + 1), max(max2_x + 1, max2_y + 1));
        }
        else {
            printf("The last domino falls after %d.0 seconds, at key domino %d.\n\n", max1, max1_x + 1);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值