DTOI T2 迷宫

【题目背景】 小K是一个探险家,这天,他遇到了一个迷宫…… 【问题描述】 迷宫可以抽象成一个矩阵,小K要从(1,1)走到(N,M),而且只能往下和往右走,即小K只能从(X,Y)走到(X,Y+1)和(X+1,Y)。小K不能走出迷宫(即X>N或Y>M)。当然,迷宫有一些格子是被堵住的,小K不能从这些格子经过。 每个没被堵住的格子都有一个权值,小K十分喜欢X这个数字和异或这个运算。所以他希望所有他经过的格子的异或和为X。现在小K想知道他有多少种走法,听说你是一位大佬,于是他向你求助。 【输入格式】 输入文件名为maze.in。 输入文件第一行为三个正整数N,M,X,表示迷宫有N行M列,小K喜欢X。 接下来的N行,每行M个正整数,其中第i行j列的正整数代表Aij,若Aij=0,则表示第?行?列被堵住了,若A??>0,这表示第?行?列没有被堵住,且权值为Aij。 输入保证A11>0且Anm>0。 【输出格式】 输出文件名为maze.out。 输出文件包含一行一个正整数,表示小K有多少种走法使得他经过的格子的异或和为X。
【输入输出样例】
maze.in
maze.out
3 3 1 1 1 5 2 3 1 0 4 5
2
【输入输出样例说明】 小K有2种走法,分别为:
(1,1)->(2,1)->(2,2)->(3,2)->(3,3)    1^2^3^4^5=1;

(1,1)->(2,1)->(2,2)->(3,2)->(3,3)    1^1^5^1^5=1;

【数据规模与约定】

Subtask 1 30%:?,?≤10

Subtask 2 20% : ?,?≤20,0≤Aij≤10,000

Subtask 3 50%:?,?≤20,0≤???≤1,000,000,000

题解:

折半搜索裸体。。。

但是考场上分析效率出问题了,没写下去。。

2333333 

#include<bits/stdc++.h>
using namespace std;
#define in inline
#define re register
#define rep(i,a,b) for(re int i=a;i<=b;i++)
#define repd(i,a,b) for(re int i=a;i>=b;i--)
#define For(i,a,b) for(int i=a;i<b;i++)
#define _(d) while(d(isdigit(ch=getchar())))
template<class T>in void g(T&t){T x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;t=f*x;}
#define p(x,y) (((x)-1)*m+(y))
typedef long long ll;
const int N=1004;
const int dx[2]={0,1},dy[2]={1,0};
int n,m,a[N][N],lim1;vector<ll>v[N*N];ll ans,x0;
in void dfs1(int x,int y,ll s1){
    s1^=a[x][y];
    if(x+y==lim1){v[p(x,y)].push_back(s1);return;}
    rep(i,0,1){
        int tx=x+dx[i],ty=y+dy[i];
        if(tx>n||ty>m||(!a[tx][ty])) continue;
        dfs1(tx,ty,s1);
    }
}
in void dfs2(int x,int y,ll s1){
    if(x+y==lim1){
        if(v[p(x,y)].empty()) return;
        ll x2=upper_bound(v[p(x,y)].begin(),v[p(x,y)].end(),x0^s1)-v[p(x,y)].begin();
        ll x1=lower_bound(v[p(x,y)].begin(),v[p(x,y)].end(),x0^s1)-v[p(x,y)].begin();
        if(v[p(x,y)][x1]==x0^s1){ans+=(ll)x2-(ll)x1;}
        return;
    }
    s1^=a[x][y];
    rep(i,0,1){
        int tx=x-dx[i],ty=y-dy[i];
        if(tx<1||ty<1||(!a[tx][ty])) continue;
        dfs2(tx,ty,s1);
    }
}
int main(){
    //freopen(".in","r",stdin);freopen(".out","w",stdout);
    g(n),g(m),g(x0);
    rep(i,1,n) rep(j,1,m) g(a[i][j]);
    lim1=(n+m+1)/2;
    dfs1(1,1,0);
    rep(i,1,n) rep(j,1,m) sort(v[p(i,j)].begin(),v[p(i,j)].end());
    dfs2(n,m,0);
    cout<<ans<<endl;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

可爱の小公举

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

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

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

打赏作者

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

抵扣说明:

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

余额充值