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;
}