• ☆ [HDU2157] How many ways?? 「矩阵乘法求路径方案数」


    传送门:>Here<

    题意:给出一张有向图,问从点A到点B恰好经过k个点(包括终点)的路径方案数

    解题思路

    一道矩阵乘法的好题!妙哉~

    话说把矩阵乘法放在图上好神奇,那么跟矩阵唯一有关的就是邻接矩阵……

    考虑邻接矩阵在这道题里的含义也就是从A到B经过1个点的方案数——能到达或不能到达。而当邻接矩阵自乘时,假设自乘一次得到矩阵B,则$b[i][j] = sumlimits_{}{}g[i][k]*g[k][j]$。因此k就作为了枚举的中介点,由于最后得到的项是累积的,所以自乘一次以后就得到了经过2个点的方案数。因此自乘k-1即能得到经过k个点的方案数。

    此时,乘法的意义就成为了每一次累积$(i->k)的方案数 * (k->j)的方案数  (起点终点固定)$ 

    Code

    /*By DennyQi*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #define  r  read()
    #define  Max(a,b)  (((a)>(b)) ? (a) : (b))
    #define  Min(a,b)  (((a)<(b)) ? (a) : (b))
    using namespace std;
    typedef long long ll;
    const int MAXN = 10010;
    const int MAXM = 27010;
    const int INF = 1061109567;
    inline int read(){
        int x = 0; int w = 1; register int c = getchar();
        while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
        if(c == '-') w = -1, c = getchar();
        while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar(); return x * w;
    }
    int N,M,K,Q,x,y,A,B;
    int g[30][30],a[30][30],b[30][30],ans[30][30][30];
    inline void Init(){
        memset(g, 0, sizeof(g));
    }
    inline void Matrix_mul(){
        memset(ans, 0, sizeof(ans));
        for(int num = 0; num <= 20; ++num){
            for(int i = 1; i <= N; ++i){
                ans[num][i][i] = 1;
            }
        }
        for(int num = 1; num <= 20; ++num){
            for(int i = 1; i <= N; ++i){
                for(int j = 1; j <= N; ++j){
                    b[i][j] = 0;
                    for(int k = 1; k <= N; ++k){
                        b[i][j] = (b[i][j] + ans[num-1][i][k] * g[k][j]) % 1000;
                    }
                }
            }
            for(int i = 1; i <= N; ++i){
                for(int j = 1; j <= N; ++j){
                    ans[num][i][j] = b[i][j];
                }
            }
        }
    }
    int main(){
        for(;;){
            N = r, M = r;
            if(!N && !M) break;
            Init();
            for(int i = 1; i <= M; ++i){
                x = r+1, y = r+1;
                g[x][y] = 1;
            }
            Matrix_mul();
            Q = r;
            while(Q--){
                A = r, B = r, K = r;
                printf("%d
    ", ans[K][A+1][B+1] % 1000);
            }
        }
        return 0;
    }
  • 相关阅读:
    理解HTTP的POST和PUT的区别
    眼见为实 — CSS的overflow属性
    Iconfont的代码使用
    JSP中contentType、pageEncoding和meta charset的区别
    在 webpack 中使用 ECharts
    MVC 中的 ViewModel
    一个简单例子理解C#的协变和逆变
    C#中使用委托、接口、匿名方法、泛型委托实现加减乘除算法
    c#打包文件解压缩
    8种主要排序算法的C#实现 (二)
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9437957.html
Copyright © 2020-2023  润新知