2019牛客暑期多校训练营(第二场)E MAZE

2019牛客暑期多校训练营(第二场)E MAZE

链接:https://ac.nowcoder.com/acm/contest/882/E
来源:牛客网
 

题目描述

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

题意:在一个N行M列的矩阵里,‘1’代表墙壁,‘0’代表道路,

输入三个数:q,a,b;

q=1: 将第a行,第b列的的数进行反转:把1变成0,或者把0变成1

q=2:输出:从第1行,第a列出发,到达最后一行第B列的次数

解题算法:矩阵+线段树+状态压缩动态规划思想

首先:从第i行走向第i+1行怎么走??

第i行:     0 0 1 0 0 1

第i+1行: 0 0 1 1 0 1

从第i行到达第i+1行可以是:

2019牛客暑期多校训练营(第二场)E MAZE_第1张图片

 

从第i-行到达第i行的方法有这么多个:2 3 0 9  8  0

从第i行到达第i+1行的方法:               6 6 0 0 17 0

就相当于这样的矩阵相乘

 

2019牛客暑期多校训练营(第二场)E MAZE_第2张图片

得出结果:

与手动推出来的一样

 

 

矩阵的第a行,第b列代表:第i行第b列的是否能够到达第i-1行的第a列,

最后用线段树维护矩阵即可

 

 

#include
using namespace std;
#define ll long long
const int maxn=50010;
int n,m,q;
const ll mod=1000000007;
struct  B
{
    int l,r;
    ll b[11][11];
}a[maxn<<2];
ll b[maxn][11];
void mul(int f1,int f2,int to){///两矩阵相乘
     for(int i=1;i<=m;i++){
 
        for(int j=1;j<=m;j++){
            ll ans=0;
            for(int k=1;k<=m;k++){
                ans+=a[f1].b[i][k]*a[f2].b[k][j]%mod;
                ans%=mod;
            }
            a[to].b[i][j]=ans;
        }
     }
     return ;
}
void pushup(int l,int i1)///构造矩阵
{
    memset(a[i1].b,0,sizeof(a[i1].b));
    for(int i=1;i<=m;i++){
 
        if(b[l][i]){
            for(int j=i;j<=m&&b[l][j];j++){
                a[i1].b[i][j]=1;
            }
            for(int j=i-1;j>0&&b[l][j];j--){
                a[i1].b[i][j]=1;
            }
        }
    }
    return ;
}
void build(int l,int r,int i){
    a[i].l=l;
    a[i].r=r;
 
    if(l==r){
        pushup(l,i);
        return ;
    }
    build(l,(l+r)/2,i<<1);
    build((l+r)/2+1,r,i<<1|1);
    mul(i<<1,i<<1|1,i);
    return ;
}
void change(int u,int i){
 
    int l=a[i].l;
    int r=a[i].r;
    if(a[i].l==a[i].r&&a[i].l==u){
        pushup(u,i);
        return ;
    }
    int mid=a[i<<1].r;
    if(u<=mid){
        change(u,i<<1);
    }else {
        change(u,i<<1|1);
    }
    mul(i<<1,i<<1|1,i);
}
int main(){
    scanf("%d%d%d",&n,&m,&q);
    char c[11];
    for(int i=1;i<=n;i++){
        scanf("%s",c);
        int lc=strlen(c);
        for(int j=0;j

 

 

 

 

 

 

 

 

你可能感兴趣的:(动态规划,数据结构,线段树)