程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Poj 1135 Domino Effect(Dijkstra)

Poj 1135 Domino Effect(Dijkstra)

編輯:C++入門知識

題目描述:
你知道多米諾骨牌除了用來玩多米諾骨牌游戲外,還有其他用途嗎?多米諾骨牌游戲:取一
些多米諾骨牌,豎著排成連續的一行,兩張骨牌之間只有很短的空隙。如果排列得很好,當你推
倒第1 張骨牌,會使其他骨牌連續地倒下(這就是短語“多米諾效應”的由來)。
然而當骨牌數量很少時,這種玩法就沒多大意思了,所以一些人在80 年代早期開創了另一個
極端的多米諾骨牌游戲:用上百萬張不同顏色、不同材料的骨牌拼成一幅復雜的圖案。他們開創
了一種流行的藝術。在這種骨牌游戲中,通常有多行骨牌同時倒下。
你的任務是編寫程序,給定這樣的多米諾骨牌游戲,計算最後倒下的是哪一張骨牌、在什麼
時間倒下。這些多米諾骨牌游戲包含一些“關鍵牌”,他們之間由一行普通骨牌連接。當一張關鍵
牌倒下時,連接這張關鍵牌的所有行都開始倒下。當倒下的行到達其他還沒倒下的關鍵骨牌時,
則這些關鍵骨牌也開始倒下,同樣也使得連接到它的所有行開始倒下。每一行骨牌可以從兩個端
點中的任何一張關鍵牌開始倒下,甚至兩個端點的關鍵牌都可以分別倒下,在這種情形下,該行
最後倒下的骨牌為中間的某張骨牌。假定骨牌倒下的速度一致。
輸入描述:
輸入文件包含多個測試數據,每個測試數據描述了一個多米諾骨牌游戲。每個測試數據的第
1 行為兩個整數:n 和m,n 表示關鍵牌的數目,1≤n<500;m 表示這n 張牌之間用m 行普通骨
牌連接。n 張關鍵牌的編號為1~n。每兩張關鍵牌之間至多有一行普通牌,並且多米諾骨牌圖案
是連通的,也就是說從一張骨牌可以通過一系列的行連接到其他每張骨牌。
接下來有m 行,每行為3 個整數:a、b 和t,表示第a 張關鍵牌和第b 張關鍵牌之間有一行
普通牌連接,這一行從一端倒向另一端需要t 秒。每個多米諾骨牌游戲都是從推倒第1 張關鍵牌
開始的。
輸入文件最後一行為n = m = 0,表示輸入結束。
輸出描述:

對輸入文件中的每個測試數據,首先輸出一行"System #k",其中k 為測試數據的序號;然後
再輸出一行,首先是最後一塊骨牌倒下的時間,精確到小數點後一位有效數字,然後是最後倒下
骨牌的位置,這張最後倒下的骨牌要麼是關鍵牌,要麼是兩張關鍵牌之間的某張普通牌。輸出格
式如樣例輸出所示。如果存在多個解,則輸出任意一個。每個測試數據的輸出之後輸出一個空行。
樣例輸入:
2 1
1 2 27
3 3
1 2 5
1 3 5
2 3 5
0 0
System #1
The last domino falls after 27.0 seconds, at key domino 2.
樣例輸出:
System #2
The last domino falls after 7.5 seconds, between key dominoes 2 and 3.

算是模版Dijkstra題目了,多了判斷哪種最優解的情況。
a) 先計算每一張關鍵牌倒下的dist[i]。這需要利用Dijkstra 算法求第1 張關鍵牌到其他每

張關鍵牌的最短路徑。然後取dist[i]的最大值,設為max1。

b) 計算每一行完全倒下的時間。設每一行的兩端的關鍵牌為i 和j,則這一行完全倒下的時

間為(dist[i] + dist[j] +
edge[i][j])/2.0,其中edge[i][j]為連接第i、j 兩張關鍵牌的行倒下

所花的時間。取所有行完全倒下時間的最大值,設為max2。

c) 如果max2 > max1,則是第②種情形;否則是第①種情形。
[cpp] 
#include <iostream> 
#include <algorithm> 
#include <cmath> 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <string> 
#define MAX 600 
#define INF 0x7FFFFFFF 
# define eps 1e-5 
using namespace std; 
int n,m; 
int edge[MAX][MAX],visit[MAX],dist[MAX];//邊的信息,訪問,最短距離 
 
void dijkstra(int u0) 

    int i,j,v; 
    for(i=1; i<=n; i++)//初始化 
    { 
        dist[i] = edge[u0][i]; 
    } 
    visit[u0] = 1; 
    for(j=0; j<n-1; j++) 
    { 
        int min = INF; 
        for(i=1; i<=n; i++) 
        { 
            if(!visit[i] && min > dist[i]) 
            { 
                min = dist[i]; 
                v = i; 
            } 
        } 
        visit[v] = 1;//點v與源點同一集合 
        for(i=1; i<=n; i++)//隨著新的頂點加入,更新dist值 
        { 
            if(!visit[i] && edge[v][i] < INF && edge[v][i] + dist[v] < dist[i]) 
                dist[i] = edge[v][i] + dist[v]; 
        } 
    } 

 
int main() 

    int i,j,a,b,c,tt = 1; 
    while(scanf("%d%d",&n,&m)) 
    { 
        if(n==0 && m==0) 
            break; 
        for(i=1; i<=n; i++)//初始化 
            for(j=1; j<=n; j++) 
            { 
                if(i == j) 
                    edge[i][j] = 0; 
                else 
                    edge[i][j] = INF; 
            } 
        for(i=0; i<m; i++)//構圖 
        { 
            scanf("%d%d%d",&a,&b,&c); 
            edge[a][b] = c; 
            edge[b][a] = c; 
        } 
        memset(visit,0,sizeof(visit)); 
        dijkstra(1);//求出1到所有定點最短路 
         
        double max1 = -10000000; 
        int index; 
        for(i=1; i<=n; i++)//情況a 
        { 
            if(max1 < dist[i]) 
            { 
                max1 = dist[i]*1.0; 
                index = i; 
            } 
        } 
         
        double max2 = -10000000; 
        int index1,index2; 
        for(i=1; i<=n; i++)//情況b 
            for(j=1; j<=n; j++) 
            { 
                if(edge[i][j] != INF && i < j)//i < j 算是優化,有了它就是0ms,沒有就是16ms 
                { 
                    if(max2 < (dist[i]+dist[j]+edge[i][j])/2.0) 
                    { 
                        max2 = (dist[i]+dist[j]+edge[i][j])/2.0; 
                        index1 = i; 
                        index2 = j; 
                    } 
                } 
            } 
             
        printf("System #%d\n",tt++); 
        if(max1 >= max2)//選出符合的情況 
            printf("The last domino falls after %.1f seconds, at key domino %d.\n",max1,index); 
        else 
            printf("The last domino falls after %.1f seconds, between key dominoes %d and %d.\n",max2,index1,index2); 
        printf("\n"); 
    } 
    return 0; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved