zoukankan      html  css  js  c++  java
  • bzoj1297 [SCOI2009]迷路

    1297: [SCOI2009]迷路

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1366  Solved: 976
    [Submit][Status][Discuss]

    Description

    windy在有向图中迷路了。 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1。 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间。

    Input

    第一行包含两个整数,N T。 接下来有 N 行,每行一个长度为 N 的字符串。 第i行第j列为'0'表示从节点i到节点j没有边。 为'1'到'9'表示从节点i到节点j需要耗费的时间。

    Output

    包含一个整数,可能的路径数,这个数可能很大,只需输出这个数除以2009的余数。

    Sample Input

    【输入样例一】
    2 2
    11
    00

    【输入样例二】
    5 30
    12045
    07105
    47805
    12024
    12345


    Sample Output

    【输出样例一】
    1

    【样例解释一】
    0->0->1

    【输出样例二】
    852

    HINT

    30%的数据,满足 2 <= N <= 5 ; 1 <= T <= 30 。 100%的数据,满足 2 <= N <= 10 ; 1 <= T <= 1000000000 。

    分析:有一道比较经典的题,求恰好经过k条边的最短路,这道题可以用矩阵乘法来做,这道题和那道题是类似的,不过边权有变化,那怎么办呢?拆点就好了,因为边权最多为9,所以每个点拆成9个点,上一个点向下一个点连边权为1的边,点与点之间连边的话,边权为几,就连向拆成的第几个点,最后矩阵快速幂就解决了.
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int mod = 2009;
    
    int n, t, maxn,b[200][200],ans[200][200],temp[200][200];
    
    int c(int x, int y)
    {
        return (y - 1) * n + x;
    }
    
    void mul1()
    {
        memset(temp, 0, sizeof(temp));
        for (int i = 1; i <= maxn; i++)
            for (int j = 1; j <= maxn; j++)
                for (int k = 1; k <= maxn; k++)
                {
                    temp[i][j] += ans[i][k] * b[k][j];
                    temp[i][j] %= mod;
                }
        memcpy(ans, temp, sizeof(ans));
    }
    
    void mul2()
    {
        memset(temp, 0, sizeof(temp));
        for (int i = 1; i <= maxn; i++)
            for (int j = 1; j <= maxn; j++)
                for (int k = 1; k <= maxn; k++)
                {
                    temp[i][j] += b[i][k] * b[k][j];
                    temp[i][j] %= mod;
                }
        memcpy(b, temp, sizeof(b));
    }
    
    void qpow(int b)
    {
        while (b)
        {
            if (b & 1)
                mul1();
            b >>= 1;
            mul2();
        }
    }
    
    int main()
    {
        scanf("%d%d", &n, &t);
        for (int i = 1; i <= n; i++)
            for (int j = 2; j <= 9; j++)
                b[c(i, j)][c(i, j - 1)] = 1;
    
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                int x;
                scanf("%1d", &x);
                if (!x)
                    continue;
                b[i][c(j, x)] = 1;
            }
        }
            maxn = n * 9;
            for (int i = 1; i <= maxn; i++)
                ans[i][i] = 1;
            qpow(t);
            printf("%d
    ", ans[1][n]);
    
        return 0;
    }
  • 相关阅读:
    8 Django 模型层(1)
    7 Django的模板层
    Java ClassLoader
    Spring的注入注解
    Java 面试Spring的加载机制
    Spring容器启动初始化bean的方法
    java 线程
    经典博客
    Spring注解@Component、@Repository、@Service、@Controller区别
    java 实现多个文件的Zip包的生成
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7545320.html
Copyright © 2011-2022 走看看