ZOJ1298, POJ1135 Domino Effect

来源:互联网 发布:软件售后工程师工资 编辑:程序博客网 时间:2024/05/22 14:13

题目大意:

        你的任务是编写程序,给定多米诺骨牌游戏,计算最后倒下的是哪一张骨牌、在什么时间倒下。这些多米诺骨牌游戏包含一些“关键牌”,他们之间由一行普通骨牌连接。当一张关键牌倒下时,连接这张关键牌的所有行都开始倒下。当倒下的行到达其他还没倒下的关键骨牌时,则这些关键骨牌也开始倒下,同样也使得连接到它的所有行开始倒下。每一行骨牌可以从两个端点中的任何一张关键牌开始倒下,甚至两个端点的关键牌都可以分别倒下,在这种情形下,该行最后倒下的骨牌为中间的某张骨牌。假定骨牌倒下的速度一致。


#include <cstdio>#include <cstdlib>const int  MAXN 500const int  INF 1000000 //无穷大int n, m;  //关键牌的数目、关键牌之间连接的数目int Edge[MAXN][MAXN];  //邻接矩阵int caseno = 1;  //测试数据序号int time[MAXN]; //tim[i]为第i 张关键牌倒下的时间(最先推倒第0张骨牌,存储时序号已减1)int S[MAXN];  //S[i]表示关键牌i 的倒下时间是否已计算void solve_case( ){    int i, j, k;  //循环变量    for( i=0; i<n; i++ )    {        time[i] = Edge[0][i]; S[i]=0;    }    time[0] = 0;   S[0] = 1;    for( i=0; i<n-1; i++ )  //Dijkstra算法:从顶点0确定n-1条最短路径    {        int MIN = INF, u = 0;        for( j=0; j<n; j++ )  //选择当前集合T中具有最短路径的顶点u        {            if( !S[j] && time[j]< MIN )            {                u=j; MIN = time[j];            }        }        S[u] = 1; //将顶点u加入到集合S,表示它的最短路径已求得        for( k=0; k<n; k++ )  //修改T集合中顶点的dist和path数组元素值        {            if( !S[k] && Edge[u][k]<INF && time[u] + Edge[u][k] < time[k] )            {                time[k] = time[u] + Edge[u][k];            }        }    }    double maxtime1 = -INF;   int pos;   //最后倒下的关键牌时间及位置    for( i=0; i<n; i++ )    {        if( time[i]>maxtime1 )        {            maxtime1 = time[i];   pos = i;        }    }    double maxtime2 = -INF, t; //每一行中间普通牌倒下的时间最大值及位置    int pos1, pos2;    for( i=0; i<n; i++ )    {        for( j=0; j<n; j++ )        {            t = (time[i]+time[j] + Edge[i][j])/2.0;            if( Edge[i][j]<INF &&   t > maxtime2 )            {                maxtime2 = t;   pos1 = i;   pos2 = j;            }        }    }    printf( "System #%d\n", caseno++ );  //输出    printf( "The last domino falls after " );    if( maxtime2>maxtime1 )        printf( "%.1f seconds, between key dominoes %d and %d.\n\n",maxtime2, pos1 + 1, pos2 + 1 );    else printf( "%.1f seconds, at key domino %d.\n\n", maxtime1, pos + 1 );}int read_case( ) //读入数据{    int i, j;  //循环变量    int v1, v2, t;  //每对连接的两张关键牌序号、时间    scanf( "%d %d", &n, &m );    if( n == 0 && m == 0 )   return 0;    for( i=0; i<n; i++ )    {        for( j=0; j<n; j++ )   Edge[i][j] = INF;  //INF表示没有连接    }    for( i=0; i<m; i++ )    {        scanf( "%d %d %d", &v1, &v2, &t);        v1--; v2--;        Edge[v1][v2] = Edge[v2][v1] = t;    }    return 1;}int main( ){    while( read_case( ) )        solve_case( );    return 0;}