2011-06-13 22:21:11Morris

d907. 3. 城市走法計數

http://zerojudge.tw/ShowProblem?problemid=d907

內容:

在網路上做地圖查詢,例如查詢Google Map,可以知道某一點走到某一點的路徑,甚至於用滑鼠拖拉可以自行更改路徑。這些路徑,不管是系統建議的,或是自行拖拉更改的,都是走得通的。也就是說,電腦必須知道任意兩個地點,有哪些路徑走得通,才能做出自動建議,並允許使用者修改。

要達到這樣的功能,所需要的資料表達方式與考慮因素很多。在此,我們將問題簡化。假設有多個城市(或地點),任意兩個城市之間只記錄有沒有路徑可通,那麼我們可以用圖形或矩陣來表達城市之間的路徑狀況,從中就可以推測並回答如下的問題:哪兩個城市沒有路徑可通?哪兩個城市必須剛好經過幾個城市才能走通,而且總共有幾種走法?

請參考下面的圖(如圖五)與矩陣(如圖六),所顯示的路徑狀況。一般而言,n個城市之間的路徑狀況,在電腦中可以用一個矩陣M來表達。其中M的每一列由上而下分別代表城市1到城市n,其每一行由左至右,也代表城市1到城市n,因此矩陣M的「第i列第j行」的值若為「1」,則代表城市i到城市j有一條直達路徑,其值若為「0」,則代表城市i到城市j沒有直達路徑。

 

154133_170534119634893_100000349195641_451599_713716_n.jpg (450×187) 

 

請根據上面的描述與範例,試寫程式,完成下列要求:

輸入說明 :

第一列為城市個數,假設為n (1≤ n ≤ 10)

第二列到第n+1列為上述矩陣的第1列到第n列,每一列由n個數字(01)表示,第i個數字表示該列中第i行的值,數字與數字中間沒有空格。

n+2列為某一城市的編號,稱為i

n+3列為另一城市的編號,稱為j (i ¹ j)

n+4列為某一整數,稱為s (1≤ s ≤ 10)

輸出說明 :

請由螢幕輸出三列數字,說明如下:

第一列輸出從城市i,經過s個城市(可重複)後,到達城市j的不同走法個數。

第二列與第三列輸出不管經過幾個城市,都無法走通的其中一對城市,且此對城市的編號都是最小,而且第二列的值小於第三列的值;若沒有走不通的城市,則都輸出0(詳見範例與說明)

範例輸入 :help

輸入範例一40110100010010010132輸入範例二40100100000000000121

範例輸出 :

輸出範例一300輸出範例二013

提示 :

156095_170534146301557_100000349195641_451600_2884553_n.jpg (573×569)

出處 :

2010三重考區 (管理:pcshic)



作法 : 矩陣乘法 & D&C
矩陣乘法,如同提示所給
接下來要判斷最小序對的不相連,直接用Floyd_Warshall O(N^3)
然後掃一次即可

/**********************************************************************************/
/*  Problem: d907 "3. 城市走法計數" from 2010三重考區                   */
/*  Language: C                                                                   */
/*  Result: AC (4ms, 272KB) on ZeroJudge                                          */
/*  Author: morris1028 at 2011-06-11 08:47:44                                     */
/**********************************************************************************/


#include<stdio.h>
#define Max 1000
typedef struct {
    int t[10][10];
}Matrix;
Matrix A, In, init;
Matrix mult(Matrix x, Matrix  y, int n) {
    Matrix t = init;
    int i, j, k;
    for(i = 0; i < n; i++)
        for(j = 0; j < n; j++)
            for(k = 0; k < n; k++) {
                t.t[i][k] += x.t[i][j]*y.t[j][k];
            }
    return t;
}
int ans(int k, int i, int j, int n) {
    Matrix x = In, y = A;
    while(k) {
        if(k&1) x = mult(x, y, n);
        y = mult(y, y, n);
        k /= 2;
    }
    return x.t[i-1][j-1];
}
int Floyd_Warshall(int n) {
    int a, b, c;
    for(a = 0; a < n; a++)
        for(b = 0; b < n; b++)
            if(A.t[a][b] == 0)
                A.t[a][b] = Max;
    for(a = 0; a < n; a++)
        for(b = 0; b < n; b++)
            for(c = 0; c < n; c++)
                if(A.t[b][a] + A.t[a][c] < A.t[b][c])
                    A.t[b][c] = A.t[b][a] + A.t[a][c];
    int tx = -1, ty = -1, flag = 1;
    for(a = 0; a < n && flag == 1; a++)
        for(b = 0; b < n && flag == 1; b++)
            if(A.t[a][b] == Max) {
                tx = a, ty = b;
                flag = 0;
            }
    printf("%d\n%d\n", tx+1, ty+1);
}
main() {
    int n, a, b, i, j, k;
    char s[11];
    while(scanf("%d", &n) == 1) {    
        for(a = 0; a < n; a++)
            for(b = 0; b < n; b++)
                A.t[a][b] = 0, In.t[a][b] = 0,
                init.t[a][b] = 0;
        for(a = 0; a < n; a++) In.t[a][a] = 1;
        
        for(a = 0; a < n; a++) {
            scanf("%s", s);
            for(b = 0; b < n; b++)
                A.t[a][b] = s[b] - '0';
        }
        scanf("%d %d %d", &i, &j, &k);
        printf("%d\n", ans(k+1, i, j, n));
        Floyd_Warshall(n);
    }
    return 0;
}