poj 1135 Domino Effect (Dijkstra)

题目大意

你知道多米诺骨牌除了用来玩多米诺骨牌游戏外,还有其他用途吗?多米诺骨牌游戏:取一些多米诺骨牌,竖着排成连续的一行,两张骨牌之间只有很短的空隙。如果排列得很好,当你推倒第张骨牌,会使其他骨牌连续地倒下(这就是短语多米诺效应的由来)。然而当骨牌数量很少时,这种玩法就没多大意思了,所以一些人在80 年代早期开创了另一个极端的多米诺骨牌游戏:用上百万张不同颜色、不同材料的骨牌拼成一幅复杂的图案。他们开创了一种流行的艺术。在这种骨牌游戏中,通常有多行骨牌同时倒下。你的任务是编写程序,给定这样的多米诺骨牌游戏,计算最后倒下的是哪一张骨牌、在什么时间倒下。这些多米诺骨牌游戏包含一些关键牌,他们之间由一行普通骨牌连接。当一张关键牌倒下时,连接这张关键牌的所有行都开始倒下。当倒下的行到达其他还没倒下的关键骨牌时,则这些关键骨牌也开始倒下,同样也使得连接到它的所有行开始倒下。每一行骨牌可以从两个端点中的任何一张关键牌开始倒下,甚至两个端点的关键牌都可以分别倒下,在这种情形下,该行最后倒下的骨牌为中间的某张骨牌。假定骨牌倒下的速度一致。
输入描述:
输入文件包含多个测试数据,每个测试数据描述了一个多米诺骨牌游戏。每个测试数据的第行为两个整数:m表示关键牌的数目,1≤n<500表示这张牌之间用行普通骨牌连接。张关键牌的编号为1n。每两张关键牌之间至多有一行普通牌,并且多米诺骨牌图案是连通的,也就是说从一张骨牌可以通过一系列的行连接到其他每张骨牌。接下来有行,每行为个整数:at,表示第张关键牌和第张关键牌之间有一行普通牌连接,这一行从一端倒向另一端需要秒。每个多米诺骨牌游戏都是从推倒第张关键牌开始的。输入文件最后一行为n = m = 0,表示输入结束。
输出描述:

对输入文件中的每个测试数据,首先输出一行"System #k",其中为测试数据的序号;然后再输出一行,首先是最后一块骨牌倒下的时间,精确到小数点后一位有效数字,然后是最后倒下骨牌的位置,这张最后倒下的骨牌要么是关键牌,要么是两张关键牌之间的某张普通牌。输出格式如样例输出所示。如果存在多个解,则输出任意一个。每个测试数据的输出之后输出一个空行。

题目分析

这是一道最短路径题目,但是要判断哪种最优解的情况。res为最后一张牌倒下的时刻,pos_ipos_j记录的是最后倒下的关键牌的标号,初始化都为-1

       a) 如果最后一张倒下的关键牌。利用Dijkstra 算法求第张关键牌到其他每张关键牌的最短路径,保存在dist[i]。然后取dist[i]的最大值,设为respos_i记录关键牌序号

b) 如果最后一张倒下的是两张关键牌之间的普通牌。设行两端的关键牌为j他们以每秒一个单位的速度相向而行,ij分别经过t1t2秒相遇,ij之间的距离为g[i][j],ij在什么时刻相遇。不难列出方程:t1+t2=g[i][j]dis[i]+g[i][j]=dis[j]+g[i][j]。则ij相遇的时刻为t=dist[i] + dist[j] +g[i][j]/2.0res=minrestpos_ipos_j记录两张关键牌的序号。(注意:要满足dis[i]+g[i][j]>dis[j]并且dis[j]+g[i][j]>dis[i]才应该计算t

c) 如果pos_j=-1,则是a;否则b况(如果b情况成立,pos_j的值应该改变了

3代码

#include<stdio.h> 

#include<string.h> 

#define MAXV 501 

#define MAXINT 999999999 

double res;

int pos_a,pos_b;

int g[MAXV][MAXV],vis[MAXV],dis[MAXV],p[MAXV]; 

void initial() 

    int i,j; 

    for(i=0;i<MAXV;i++) 

    { 

        vis[i]=0; 

dis[i]=MAXINT;

        p[i]=-1;

for(j=0;j<MAXV;j++)

{

if(i!=j)

g[i][j]=MAXINT; 

}

    } 

res=-MAXINT;

pos_a=-1;

pos_b=-1;

void dijkstra(int nvertex,int start) 

    int v,i,j,distance; 

    dis[start]=0; 

    v=start; 

    while(!vis[v]) 

    { 

        vis[v]=1; 

        for(i=1;i<=nvertex;i++) 

        { 

            if(!vis[i] && dis[i]>(dis[v]+g[v][i])) 

            { 

                dis[i]=dis[v]+g[v][i]; 

                p[i]=v; 

            } 

        } 

        distance=MAXINT; 

        for(i=1;i<=nvertex;i++) 

        { 

            if(!vis[i] && dis[i]<distance) 

            { 

                distance=dis[i]; 

                v=i; 

            } 

        } 

    } 

for(i=1;i<=nvertex;i++)

{

if(res<dis[i])

{

res=dis[i];

pos_a=i;

}

}

double temp;

for(i=1;i<=nvertex;i++)

{

for(j=1;j<=nvertex;j++)

{

if(i!=j && g[i][j]<MAXINT && dis[i]+g[i][j]>dis[j] && dis[j]+g[i][j]>dis[i])

{

temp=1.0*(dis[i]+dis[j]+g[i][j])/2;

if(res<temp)

{

res=temp;

if(i<j)

{

pos_a=i;

pos_b=j;

}

else

{

pos_a=j;

pos_b=i;

}

}

}

}

}

int main() 

    int n,m,count=1; 

    while(2==scanf("%d%d",&n,&m)) 

    { 

        if(0==n && 0==m)

            break; 

        initial(); 

int i,a,b,c;

        for(i=1;i<=m;i++) 

        { 

            scanf("%d%d%d",&a,&b,&c); 

                g[a][b]=g[b][a]=c; 

        } 

        dijkstra(n,1);

        printf("System #%d\n",count++); 

if(-1==pos_b)

printf("The last domino falls after %.1lf seconds, at key domino %d.\n\n",res,pos_a);

else

printf("The last domino falls after %.1lf seconds, between key dominoes %d and %d.\n\n",res,pos_a,pos_b);

    } 

    return 0; 

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值