1. 程式人生 > >【矩陣乘法】迷路

【矩陣乘法】迷路

SCOI2009第二試第三題

迷路

(road.pas/in/out)

【問題描述】

windy在有向圖中迷路了。

該有向圖有 N 個節點,windy從節點 0 出發,他必須恰好在 T 時刻到達節點 N-1。

現在給出該有向圖,你能告訴windy總共有多少種不同的路徑嗎?

注意:windy不能在某個節點逗留,且通過某有向邊的時間嚴格為給定的時間。

【輸入格式】

輸入檔案road.in第一行包含兩個整數,N T。

接下來有 N 行,每行一個長度為 N 的字串。

第i行第j列為'0'表示從節點i到節點j沒有邊。

為'1'到'9'表示從節點i到節點j需要耗費的時間。

【輸出格式】

輸出檔案road.out包含一個整數,可能的路徑數,這個數可能很大,只需輸出這個數除以2009的餘數。

【輸入樣例一】

2 2

11

00

【輸出樣例一】

1

【樣例解釋一】

0->0->1

【輸入樣例二】

5 30

12045

07105

47805

12024

12345

【輸出樣例二】

852

【資料規模和約定】

30%的資料,滿足 2 <= N <= 5 ; 1 <= T <= 30 。

100%的資料,滿足 2 <= N <= 10 ; 1 <= T <= 1000000000 。

看著就很熟悉,聯想起了過去講過的矩陣乘法的應用,求T時刻到達某一點的總方案數。

過去的模型時單位時間內能走過1個格子。

這道題不一樣,不同的路線花的時間不一樣。

我沒有想出解決方案來,OJ指出了方向,拆點。

O(lgn)的複雜度,已經到極限了。

一開始走了很多彎路,在過程中受到指點,改正了很多地方

1)一開始拆點的方法不好,用了慣用的在所有點之後附加點的方法(平常超級源超級匯的處理方法,拆點我一般都用連結串列,但是此題不行,因為是矩陣),一直弄不好。WJJ指出了更好的方法,即給每一個點開一段連續的記憶體,儲存該點和它拆的點。因此我感到,不僅要分析演算法的優劣,分析儲存方式也很重要,如果因為儲存方式不好,而導致實現好演算法實現困難就得不償失了。

2)我一開始打快速冪的模板很容易就直接寫矩陣的類了,結果很難打。最好不要寫類。。

3)單位矩陣是主對角線上為1,我以為是全是1

4)快速冪的返回值沒有用,記得返回,記得要用

。。。。。。。。未完待定

#include <cstdio>

long target;

struct Matrix
{
    long size;
    long map[110][110];
//    long operator[](long i,long j){return map[i][j];}
    Matrix(long M2[110][110],long _size)
    {
        size = _size;
        for (long i=0;i<size;i++)
        {
            for (long j=0;j<size;j++)
            {
                map[i][j] = M2[i][j];
            }
        }
    }
//    Matrix operator*(Matrix& M2)
//    {
//        long _m[110][110];
//        for (long i=1;i<size+1;i++)
//        {
//            for (long k=1;k<size+1;k++)
//            {
//                for (long j=1;j<size+1;j++)
//                {
//                    _m[i][j] += map[i][k]*M2.map[k][j];
//                }
//            }
//        }
//        return Matrix(_m,size);
//    }
    void operator*=(Matrix& M2)
    {
        long _m[110][110];
        for (long i=0;i<size;i++)
            for (long j=0;j<size;j++)
                _m[i][j] = 0;

        for (long i=0;i<size;i++)
        {
            for (long j=0;j<size;j++)
            {
                for (long k=0;k<size;k++)
                {

                    (_m[i][j] += map[i][k]*M2.map[k][j])%= 2009;
                }
            }
        }
        for (long i=0;i<size;i++)
            for (long j=0;j<size;j++)
                map[i][j] = _m[i][j];
    }
//    void operator%=(long c)
//    {
//        for (long i=0;i<size;i++)
//        {
//            for (long j=0;j<size;j++)
//            {
//                map[i][j] %= c;
//            }
//        }
//    }
    long get(long i,long j){return map[i][j];}
    Matrix(long _num,long _size)
    {
        size = _size;
        for (long i=0;i<size;i++)
        {
                map[i][i] = _num;
        }
    }
    void operator=(Matrix& M2)
    {
        size = M2.size;
        for (long i=0;i<size;i++)
        {
            for (long j=0;j<size;j++)
            {
                map[i][j] = M2.map[i][j];
            }
        }
    }
};
long _map[110][110];
long cnt;

template<typename TYPE>
void qpower(TYPE &a,long b)
{
    TYPE pow = a;
    TYPE ans (1,cnt);
    while (b)
    {
        if (b&1){ans*=pow;}
        pow*=pow;
        b >>= 1;
    }
    a = ans;
}

long n;long t;

int main()
{
    freopen("road.in","r",stdin);
    freopen("road.out","w",stdout);

    scanf("%ld%ld",&n,&t);
    cnt = n*9;
    for (long i=0;i<n;i++)
    {
        scanf("\n");
        for (long j=0;j<n;j++)
        {
            char tmp ;
            scanf("%c",&tmp);
            tmp -= '0';
            if (tmp == 1)
            {
                _map[i*9][j*9] = 1;
            }
            else if (tmp > 1)
            {
                _map[i*9][j*9+tmp-1] = 1;
                for (long k=j*9+tmp-1;k>j*9;k--)
                {
                    _map[k][k-1] = 1;
                }
            }
        }
    }
    Matrix map(_map,cnt);
    qpower(map,t);
    #ifdef Debug
//    printf("\t ");
//    for (long i=0;i<n*9+1;i++)
//        printf("%ld\t",i);
//    printf("\n");
//    for (long i=0;i<n*9+1;i++)
//        printf("-----");
//
//    for (long i=0;i<n*9+1;i++)
//    {
//        printf("\n%ld\t|",i);
//        for (long j=0;j<n*9+1;j++)
//        {
//            if (map.get(i,j) == 1)
//                printf("%ld\t",1);
//            else
//                printf(" \t");
//        }
//    }
    #endif
    printf("%ld",map.get(0,n*9-9)%2009);
    return 0;

}

//long _ma[3][3] = {{1,2,0},{0,1,1},{0,0,1}};
//int main()
//{
//    Matrix m1(1,3);
//    Matrix m2(1,3);
//    Matrix m3 = m1;
//    m3 *= m2;
//    return 0;
//}