1. 程式人生 > 實用技巧 >習題:Xor-Paths(折半搜尋)

習題:Xor-Paths(折半搜尋)

題目

傳送門

思路

一道還可以的折半搜尋的題目

路徑的長度必然為\(n+m-1\)

如果直接暴力來做,時間複雜度即為\(2^{n+m-1}\),必然會爆炸

但是考慮到\(2^\frac{n+m-1}{2}\)的複雜度可以接受,就可以用折半搜尋

剩下的用一個map來存一下幾個

程式碼

#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
int n,m;
long long k;
int dx[5]={0,1,0,-1,0};
int dy[5]={0,0,1,0,-1};
long long w[25][25],ans;
map<long long,long long> t[25][25];
bool inside(int x,int y)
{
    if(1<=x&&x<=n&&1<=y&&y<=m)
        return 1;
    return 0;
}
void dfs1(int x,int y,int dep,int limit,long long done)
{
    if(dep>limit)
    {
        t[x][y][done]++;
        return;
    }
    done^=w[x][y];
    for(int i=1;i<=2;i++)
    {
        int tx=x+dx[i];
        int ty=y+dy[i];
        if(inside(tx,ty))
            dfs1(tx,ty,dep+1,limit,done);
    }
}
void dfs2(int x,int y,int dep,int limit,long long done)
{
	done^=w[x][y];
    if(dep==limit)	
    {
        ans+=t[x][y][k^done];
        return;
    } 
    for(int i=3;i<=4;i++)
    {
        int tx=x+dx[i];
        int ty=y+dy[i];
        if(inside(tx,ty))
            dfs2(tx,ty,dep+1,limit,done);
    }
}
int main()
{
	ios::sync_with_stdio(false);
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>w[i][j];
    dfs1(1,1,1,(n+m-1)/2,0);
    dfs2(n,m,1,(n+m-1)-(n+m-1)/2,0);
    cout<<ans;
    return 0;
}