【问题描述】
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 。
此题考察矩阵乘法。首先注意到每条边的权值取值范围为[0, 10),所以拆点,将每个点拆成9个点,即将点i拆为[9i, 9i+9]9个点,并且对于每个t ∈[9i, 9i+9)都从t到t+1连一条权值为1的边。
读入数据,若其中i到j有边,且权值为t(t > 0,这个非常重要!),则从9i+t-1到9j连一条权值为1的边(这样做的目的是保证从i到j经时间t)。
求以上所得矩阵的T次方,并输出0到9n-9的权值即可。
提交情况:提交2次。
第一次30分,WrongAnswer * 7;(乘法取余出错。)
第二次100分。
ACCode:
#include <cstdio>
#include <cstring>
#include <cstdlib>
const char fi[] = "road.in";
const char fo[] = "road.out";
const int maxR = 20;
const int maxN = 210;
const int MOD = 2009;
const int maxT = 9;
typedef int Matrix[maxN][maxN];
int tmp[maxR][maxR];
Matrix mp = {0};
int n, T;
void init_file()
{
freopen(fi, "r", stdin);
freopen(fo, "w", stdout);
return;
}
void readdata()
{
scanf("%d%d", &n, &T);
for (int i = 0; i < n; ++i)
{
getchar();
for (int j = 0; j < n; ++j)
tmp[i][j] = getchar() - '0';
}
for (int i = 0; i < n; ++i)
for (int k = 1; k < maxT; ++k)
mp[i * maxT + k - 1][i * maxT + k] = 1;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
if (tmp[i][j]) //有边才能连边,否则无意义且出错。
mp[i * maxT + tmp[i][j] - 1][j * maxT] = 1;
n *= maxT;
return;
}
void Mul(Matrix &a, Matrix b)
{
Matrix ans = {0};
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
for (int k = 0; k < n; ++k)
(ans[i][j] += a[i][k] * b[k][j]) %= MOD;
//这里应注意容易出错。
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
a[i][j] = ans[i][j];
return;
}
void Power(Matrix &mp, int T)
{
Matrix ans, tmp;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
{
ans[i][j] = 0;
tmp[i][j] = mp[i][j] % MOD;
}
for (int i = 0; i < n; ++i)
ans[i][i] = 1;
for (; T; T >>= 1)
{
if (T & 1) Mul(ans, tmp);
Mul(tmp, tmp);
}
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
mp[i][j] = ans[i][j] % MOD;
return;
}
void work()
{
Power(mp, T);
printf("%d\n", mp[0][n - maxT]);
return;
}
int main()
{
init_file();
readdata();
work();
return 0;
}