MAZE

MAZE

Given a maze with N rows and M columns, where bijb_{ij}bij​ represents the cell on the i-row, j-th column. If bi,j="1"b_{i, j} = \texttt{“1”}bi,j​=“1”, it’s a wall and can’t not be passed. If you are on the cell bi,jb_{i, j}bi,j​, you can go to b(i+1),jb_{(i+1), j}b(i+1),j​, bi,(j−1)b_{i, (j-1)}bi,(j−1)​, or bi,(j+1)b_{i, (j+1)}bi,(j+1)​ as long as it’s not a wall.

Sometime, a cell may be changed into wall, or vise versa. You need to find out the number of way to pass through the maze starting at some given cell and finishing at some given cell.

If the starting cell or finishing cell is a wall, there’s clearly no way to pass through the maze.

Note that you can’t go back to the cell you just from.
输入描述:

The first line of input contains three space-separated integers N, M, Q.
Following N lines each contains M characters bijb_{ij}bij​ representing the maze.
Following Q lines each contains three space-separated integers qi,ai,biq_i, a_i, b_iqi​,ai​,bi​.

If qi=1q_i = 1qi​=1, the state of cell bai,bib_{a_i, b_i}bai​,bi​​ is changed.
If qi=2q_i = 2qi​=2, you need to find out the number of way to start at cell b1,aib_{1, a_i}b1,ai​​ and finish at cell bN,bib_{N, b_i}bN,bi​​.

1≤N,Q≤500001 \leq N, Q \leq 500001≤N,Q≤50000
1≤M≤101 \leq M \leq 101≤M≤10
bij∈"01"b_{ij} \in \texttt{“01”}bij​∈"01"
1≤qi≤21 \leq q_i \leq 21≤qi​≤2
If qi=1q_i = 1qi​=1, 1≤ai≤N1 \leq a_i \leq N1≤ai​≤N and 1≤bi≤M1 \leq b_i \leq M1≤bi​≤M.
If qi=2q_i = 2qi​=2, 1≤ai,bi≤M1 \leq a_i, b_i \leq M1≤ai​,bi​≤M.

输出描述:

For each qi=2q_i = 2qi​=2, Output one line containing an integer representing the answer module 109+7(1000000007)10^9+7(1000000007)109+7(1000000007).

示例1
输入
复制

2 2 3
00
00
2 1 2
1 1 2
2 1 2

输出
复制

2
1

题解:
这题刚看到感觉好难完全没有思路,后来看了看题解才弄明白怎么做。我就简单说一下思路吧!
mp[i][j] 表示迷宫的地图

首先要回这题你必须要知道的知识,线段树,矩阵乘,dp
先来一个一个说。
先从 dp开始,这题怎么dp呢?
我们可以 dp[i][j] 表示必须经过 mp[i][j-1]
那么要想求到 (x,y)的所有路径dp[x+1][y] 就是答案了。

转移方程式怎么写呢?
自己想一下我们要求dp[i][j] 且必须经过 (i-1,j)这点,那么dp[i][j]就从 i-1这层转移了。
也就是 dp[i][j]=dp[i-1][j-1]+dp[i-1][j-2]…+dp[i-1][j-k]+dp[i-1][j]+dp[i-1][j+1]+…dp[i-1][j+z];
且 j-k到j+z 那层的mp 也就是mp[i][j-k到j+z]都为0;

来举个例子吧
比如 mp为

00
00

现在起点是(1,1),终点是(2,2);
先让dp[1][1]=1,其它都是0;至于为啥?读者自己想一下。
dp就变成

10
11
22

其实仔细推一下就是:

比如,dp[2][2]=dp[1][1]+dp[1][2]+dp[1][3],那么在矩阵中第二列前三个为1,后三个为0

好了,现在有了转移矩阵,我们要求从 (1, x) 走到 (n, y) 的方案数,即令 dp[1][x] = 1,求 dp[n + 1][y]​​​​​​​

则可以用矩阵表示,ans=Π M1 ~ Mn​​​​​​​(连乘),取ans[x][y]即可。
看不懂看别人家的吧不想写了。。。。
别人家

#include<bits/stdc++.h>
using namespace std;
const int N = 5e4 + 7;
typedef long long ll;
const ll mod = 1e9 + 7;
struct node{
    ll mtrix[15][15];
} tree[4 * N];
 
int mp[N][15], n, q, mm;
ll dp[N][15];
 
void mutil(ll a[15][15],ll b[15][15],ll c[15][15]){
    for (int i = 1; i <= 10;i++){
        for (int j = 1; j <= 10;j++){
            c[i][j] = 0;
        }
    }
    for (int i = 1; i <= 10; i++){
        for (int j = 1; j <= 10; j++){
            for (int k = 1; k <= 10; k++){
                c[i][j] = (c[i][j] % mod + (a[i][k] * b[k][j]) % mod) % mod;
            }
        }
    }
}
 
void make(ll a[15][15],int index){
    for (int i = 1,j; i <= 10;i++){
        for (j = i; j <= 10&&mp[index][j]==0;j++){
            a[j][i] = 1;
        }
        for (; j <= 10;j++){
            a[j][i] = 0;
        }
             
        for (j = i; j >= 0&&mp[index][j]==0;j--){
             a[j][i] = 1;
        }
        for (j; j >= 0;j--){
            a[j][i] = 0;
        }
    }
}
 
#define m (l+r)/2
#define lson 2*node
#define rson 2*node+1
 
 
void build(int l,int r,int node){
    if(l==r){
        make(tree[node].mtrix, l);
        return;
    }
    build(l, m, lson);
    build(m + 1, r, rson);
    mutil(tree[lson].mtrix, tree[rson].mtrix, tree[node].mtrix);
 
}
 
void update(int pos, int l,int r,int node){
    if(l==r){
        make(tree[node].mtrix, l);
        return;
    }
    if(pos<=m)
        update(pos, l, m , lson);
    else
        update(pos, m + 1, r, rson);
    
    mutil(tree[lson].mtrix, tree[rson].mtrix, tree[node].mtrix);
}
 
int main(){
    scanf("%d%d%d", &n, &mm, &q);
    for (int i = 1; i <= n;i++){
        for (int j = 1; j <= 10;j++){
            mp[i][j] = -1;
        }
    }
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= mm; j++){
            scanf("%1d", &mp[i][j]);
        }
    }
    build(1, n, 1);
    int a, b, c;
    while(q--){
        scanf("%d%d%d", &a, &b, &c);
        if(a==1){
            if(mp[b][c]==1){
                mp[b][c] = 0;
            }else{
                mp[b][c] = 1;
            }
            update(b, 1, n, 1);
        }else{
 
            printf("%lld\n", tree[1].mtrix[b][c]);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值