zoukankan      html  css  js  c++  java
  • BZOJ1297 迷路

    传送门

    题目大意:

    输入n(点的数量),t(时间),和一个n*n的矩阵,第i行第j列表示第i个节点到第j个节点有一条matrix[i]j时间的边,若为0则没有边,问从1到n恰好经过t时间的方案数有多少种?

    题目分析:

    矩阵的幂与路径的联系:若i到j有一条边权为1的边,那么matrix[i][j]=1,(matrix^k)中的[1][n]即代表1到n距离恰好k的方案数(同样也可以表示:i到j有一条边,1到n的经过边数恰好为k的方案数。)
    这道题目简化后是:知道i到j有边权为1的边,求x到y的距离为k的方案总数,正是上面提到的。
    加上边权后不能套用上边直接求解,因为上面的做法只针对权值为1。但由于一条边的权值只从0~9,那么可以将一个点拆成9个点,若i到j有一条边权为k的边,就相当于从i拆出的第k个节点向j拆出的第1个点连边,i拆出的点之间连边权为1的边,这样(matrix^t)的[getkth(i, 1)][getkth(n, 1)]即表示方案数。(getkth表示i拆出的第j个点)

    code

    #include<bits/stdc++.h>
    using namespace std;
    
    namespace IO{
        inline int read(){
            int i = 0, f = 1; char ch = getchar();
            for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
            if(ch == '-') f = -1, ch = getchar();
            for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
            return i * f;
        }
        inline void wr(int x){
            if(x < 0) putchar('-'), x = -x;
            if(x > 9) wr(x / 10);
            putchar(x % 10 + '0');
        }
    }using namespace IO;
    
    const int N = 15, Mod = 2009;
    int n, T;
    struct node{
        int b[N*10][N*10]; //每个点拆成9个
        node(){}
        inline void init(){
            memset(b, 0, sizeof b);
        }
        inline void set(int p, int q, int z){b[p][q] = z;}
        inline void I(){
            //初始化为单位矩阵
            memset(b, 0, sizeof b);
            for(int i = 1; i <= n*9; i++)
                set(i, i, 1);
        }
        inline node operator * (const node &p) const{
            node ret;
            for(int i = 1; i <= n*9; i++)
                for(int j = 1; j <= n*9; j++){
                    int sum = 0;
                    for(int k = 1; k <= n*9; k++) sum = (sum + b[i][k] * p.b[k][j]) % Mod;
                    ret.set(i, j, sum);
                }
            return ret;
        }
        inline node operator ^ (int tt){
            node ret; ret.I();
            node tmp = *this;
            for(; tt; tt >>= 1, tmp = tmp * tmp) if(tt & 1) ret = ret * tmp;
            return ret;
        }
    }matrix, ret;
    
    inline int getkth(int x, int k){
        return (x-1) * 9 + k;
    }
    
    int main(){
        n = read(), T = read();
        matrix.init(), ret.init();
        for(int i = 1; i <= n; i++) 
            for(int j = 1; j <= 8; j++){
                matrix.set(getkth(i, j), getkth(i, j + 1), 1);
            }
        for(int i = 1; i <= n; i++){
            char c[N]; scanf("%s", c + 1);
            for(int j = 1; j <= n; j++){
                int x = c[j] - '0';
                if(x) matrix.set(getkth(i, x), getkth(j, 1), 1); 
            }
        }
        ret = matrix ^ T;
        wr(ret.b[getkth(1, 1)][getkth(n, 1)]);
        return 0;
    }
    
    
  • 相关阅读:
    随笔2
    随笔
    关于updateElement接口
    随笔1
    本地访问正常,服务器访问乱码 记录
    Redis (error) NOAUTH Authentication required.解决方法
    tomcat启动很慢 停留在 At least one JAR was scanned for TLDs yet contained no TLDs.
    微信公众号消息回复
    微信公众号 报token验证失败
    idea中web.xml报错 Servlet should have a mapping
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7695591.html
Copyright © 2011-2022 走看看