题目链接:C 筱玛的迷阵探险
题意:给定一个n*n(
n
<
=
20
n<=20
n<=20)大小的矩阵,矩阵中的每个点上有一个数字,初始时,你自身有一个数字,现在让你从(1,1)走到(n,n),每次只能向下或向右走,将路径上的数字以及你自身的数字异或起来,问最小的异或值为多少。
首先考虑数据最值,直接大力搜索的话复杂度为
C
40
20
C_{40}^{20}
C4020,复杂度很高。
所以我们可以将路径拆为从(1,1)走20步到(x,y),再从(x,y)走20步道(n,n),这两个分开计算复杂度为:
2
∗
C
20
10
2*C_{20}^{10}
2∗C2010,路径计算最大异或和的话,就需要用到字典树,我们枚举行号,建立字典树,计算答案即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=6e6+7;
#define int long long
int trie[maxn][2];
int tot=1;
void insert(int x){
int p=1,id;
for(int i=30;i>=0;--i){
id=((x>>i&1)?1:0);
if(!trie[p][id]) trie[p][id]=++tot;
p=trie[p][id];
}
}
int myfind(int x){
int p=1,id;
int res=0;
for(int i=30;i>=0;--i){
id=((x>>i&1)?1:0);
if(trie[p][!id]) res+=(1<<i),p=trie[p][!id];
else p=trie[p][id];
}
return res;
}
void init(){
memset(trie,0,sizeof(trie));
tot=1;
}
int n;
int a[29][29];
int getid(int x,int y){ return x*n+y; }
vector<int> v1[29],v2[29];
bool check(int x,int y){
if(x>=1&&x<=n&&y>=1&&y<=n) return 1;
return 0;
}
int e;
void dfs1(int x,int y,int step,int val){
if(step==n){
v1[x].push_back(val^e);
return ;
}
if(check(x,y+1)) dfs1(x,y+1,step+1,val^a[x][y+1]);
if(check(x+1,y)) dfs1(x+1,y,step+1,val^a[x+1][y]);
}
void dfs2(int x,int y,int step,int val){
if(step==n){
v2[x].push_back(val);
return ;
}
if(check(x-1,y)) dfs2(x-1,y,step+1,val^a[x-1][y]);
if(check(x,y-1)) dfs2(x,y-1,step+1,val^a[x][y-1]);
}
signed main(){
scanf("%lld%lld",&n,&e);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) scanf("%lld",&a[i][j]);
if(n==1){
printf("%lld\n",e^a[1][1]);
return 0;
}
dfs1(1,1,1,a[1][1]);
dfs2(n,n,1,a[n][n]);
int maxx=0;
for(int i=1;i<=n;++i){
init();
for(int j=0;j<v2[i].size();++j) insert(v2[i][j]);
for(int j=0;j<v1[i].size();++j) maxx=max(maxx,myfind(v1[i][j]));
}
printf("%lld\n",maxx);
return 0;
}