迷宫

题目描述

迷宫可以抽象成一个矩阵,小K要从(1,1)走到(N,M),而且只能往下和往右走,即小K只能从(X,Y)走到(X,Y+1)和(X+1,Y)。小K不能走出迷宫(即X>N或Y>M)。当然,迷宫有一些格子是被堵住的,小K不能从这些格子经过。 每个没被堵住的格子都有一个权值,小K十分喜欢X这个数字和异或这个运算。所以他希望所有他经过的格子的异或和为X。现在小K想知道他有多少种走法,听说你是一位大佬蒟蒻 ,于是他向你求助。
N , M &lt; = 20 , A i &lt; = 1 e 9 N,M&lt;=20,Ai&lt;=1e9 N,M<=20,Ai<=1e9

题解

考虑到这道题有神奇的 N , M &lt; = 20 N,M&lt;=20 N,M<=20应该是个暴力题,考虑走所有的点,应该有 C 40 20 = 137846528820 = 1.3 e 11 C^{20}_{40}=137846528820=1.3e11 C4020=137846528820=1.3e11种走法,然而当我们看到这种尴尬数据级别的时候,有个神奇的东西叫做折半搜索,我们可以让它在 x + y = n x+y=n x+y=n的位置停下来,方案数大概是开根号级别的 1 e 6 1e6 1e6左右,开个map即可

代码

#include<bits/stdc++.h>
#define maxn 205
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
LL read(){
    LL res,f=1; char c;
    while(!isdigit(c=getchar())) if(c=='-') f=-1; res=(c^48);
    while(isdigit(c=getchar())) res=(res<<3)+(res<<1)+(c^48);
    return res*f;
}
int n,m,p,a[maxn][maxn];
LL ans;
map<int,int> M[maxn];
void DFS(int x,int y,int sum){
    if(!a[x][y]) return;
    if(x+y==n+1){
        M[x][sum]++;
        return ;
    }
    if(x<n) DFS(x+1,y,sum^a[x][y]);
    if(y<m) DFS(x,y+1,sum^a[x][y]);
}
void _DFS(int x,int y,int sum){
    if(!a[x][y]) return;
    if(x+y==n+1){
        ans+=M[x][sum];return;
    }
    if(x>1) _DFS(x-1,y,sum^a[x-1][y]);
    if(y>1) _DFS(x,y-1,sum^a[x][y-1]);
}
int main(){
    n=read(); m=read(); p=read();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            a[i][j]=read();
        }
    }
    DFS(1,1,0);
    _DFS(n,m,p^a[n][m]);
    printf("%lld\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jarden_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值