给定一个R * C不超过20的图,一开始人在(1,1)然后给出之多100000个时间序列(按时间递增给出),
每个时间可能发生的事情是在某个位置出现猫(有猫的地方人不能存在),猫在某个位置消失,询问人从1,1点在1时刻出发在t时刻可以走到(x , y)的所有可行性路径数目。
分析:
典型的矩阵转移题目。
初始时用一个人d[ i ][ j]....代表人从1,1出发走了当前步数,可以走到1的路径数为i,走到2的路径数目为j,.......
那么转移矩阵 m[ ][ ] 代表的是从i - > j的所有可行路经数目,中间加上矩阵快速幂即可。
#include <bits/stdc++.h>
#define fst first
#define snd second
#define ALL(a) a.begin(), a.end()
#define clr(a, x) memset(a, x, sizeof a)
#define rep(i,x) for(int i=0;i<(int)x;i++)
#define rep1(i,x,y) for(int i=x;i<=(int)y;i++)
#define LOGN 22
typedef long long ll;
using namespace std;
const int mod = 1e9 + 7;
struct Matrix{
int m[22][22];
void standard(int n){
rep(i,n) rep(j,n) m[i][j]=(i==j);
}
void show(int n){
rep(i,n){
rep(j,n) cout<<m[i][j]<<" ";
cout<<endl;
}
}
};
int n;
Matrix mul(Matrix A,Matrix B){
Matrix C;
rep(i,n) rep(j,n){
C.m[i][j] = 0;
rep(k,n) C.m[i][j] =(C.m[i][j] + (ll)A.m[i][k]*B.m[k][j]%mod)%mod;
}
return C;
}
Matrix pow_(Matrix A,int c){
Matrix ret ; ret.standard(n);
while(c > 0){
if(c & 1) ret=mul(ret,A);
A=mul(A,A);
c>>=1;
}
return ret;
}
const int dx[]={-1 , 0 ,1, 0};
const int dy[]={ 0 , 1 ,0,-1};
int r , c , q;
int main()
{
scanf("%d %d %d",&r,&c,&q);
n = r * c;
Matrix A; A.standard(n);
rep(i , r) rep(j , c){
rep(d , 4){
int ni = i + dx[d] , nj = j + dy[d];
if(ni>=0 && ni < r && nj >= 0 && nj < c)
A.m[i*c + j][ni*c+nj]=1;
}
}
Matrix all , now; all.standard(n);
int pret = 1 , vis[22]={0};
while(q--){
int cmd,x,y,t;
scanf("%d %d %d %d",&cmd,&x,&y,&t),--x,--y;
rep(i , n) rep(j , n){
if(!vis[i] && !vis[j]) now.m[i][j] = A.m[i][j];
else now.m[i][j] = 0;
}
all = mul(all , pow_(now , t - pret));
pret = t;
if(cmd == 2) vis[x*c + y] = 1;
else if(cmd == 3)vis[x*c + y] = 0;
else if(cmd == 1) printf("%d\n",all.m[0][x*c + y]);
}
return 0;
}