ZOJ 1298_Domino Effect

题意:

多米诺骨牌效应:若干个关键牌相连,关键牌之间含有普通牌,关键牌倒下后其所在的行的普通牌全部倒下。求从推倒1号关键牌开始,最终倒下的牌的位置及时间。

分析:

最终倒下的牌的位置有两种情况,要么是正好为关键牌,要么是在两个关键牌之间的普通牌。前者可以利用最短路求出每个关键牌倒下的时间,而各行普通牌全部倒下的时间为该行两个关键牌倒下时间与该行从一端倒向另一端的时间和的一半,即 (t[i]+t[j]+e[i][j])/2,选出两种情况的最大值进行比较,两者中较大值即为多米诺骨牌完全倒下的时间。

代码:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
#define rep(i,a,n) for(int i =(a); i < (n); i++)
#define sa(n) scanf("%d",&(n))
int n;
const int maxn=550;
const int INF=0x3fffffff;
int t[maxn],s[maxn],e[maxn][maxn];
void dijkstra()
{
    int u;
    rep(i,0,n){
        t[i]=e[0][i];s[i]=0;
    }
    t[0]=0;
    rep(i,0,n-1){
        int  mins = INF;
        rep(j,0,n){
            if(!s[j]&&t[j]<mins){
                u=j;
                mins=t[j];
            }
        }
        s[u]=1;
        rep(k,0,n){
            if(!s[k]&&e[u][k]<INF)
                t[k]=min(t[k],e[u][k]+t[u]);
        }
    }
}
int main(void)
{
    int m,c=1;
    int a,b,l;
    sa(n);sa(m);
    while(n!=0||m!=0){
       fill(t,t+maxn,INF);
       rep(i,0,n) rep(j,0,n) e[i][j]=INF;
       rep(i,0,m){
           sa(a);sa(b);sa(l);
            e[a-1][b-1]=e[b-1][a-1]=l;
        }

    dijkstra();

    double maxtime=0;
    int p=1;
    rep(i,0,n){
        if(maxtime<t[i]){
            maxtime=t[i];
            p=i+1;
        }
    }
    double time,emax=0;
    int p1,p2;
    rep(i,0,n){
        rep(j,0,n){
            if(e[i][j]<INF){
                 time=(t[i]+t[j]+e[i][j])/2.0;
                if(time>emax){
                    emax=time;
                    p1=i+1;p2=j+1;
                }
            }
        }
    }
    printf("System #%d\n",c++);
    if(maxtime<emax)
        printf("The last domino falls after %.1f seconds, between key dominoes %d and %d.\n\n",emax,p1,p2);
    else
        printf("The last domino falls after %.1f seconds, at key domino %d.\n\n",maxtime,p);
     sa(n);sa(m);
    }
    return 0;
}

转载于:https://www.cnblogs.com/Tuesdayzz/p/5758856.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值