rank :153 虽然打的很惨,但是也没有抽中奖,啊哈哈哈
题数 :1
补题 :
可惜可惜啊,空间复杂度分析不到位,数组开小了 一直没过。
思路 :根据 n的大小,发现 dfs 直接从 (1,1)到 (n,n)是肯定超时的,而且每一步也没有最优解,
无法进行记忆化,只能全部结果保存,想到了折半搜索 就是 从 (1,1)搜到 对角线 ,
然后记录下所有结果 ,再从 (n,n)搜到对角线,与记录的结果对拍一下 ,取最值即可。
这个要注意的是必须 是在一个会合的值才是合法的 ,所以 要根据 行标去存储第一次折半
从 (1,1)到对角的值。因为对角线上的点 行 坐标都是唯一的,并且根据本题的要求,
求异或最大值需要用字典树 ,根据行标建立 20 棵字典树 即可 。
#include<bits/stdc++.h>
using namespace std;
#define maxn 25
#define ll long long
ll a[maxn][maxn],e,n;
ll tree[25][3023456][3];
ll id[55],ans;
void updata(int cp,ll x)
{
int p=0;
for(int i=32; i>=0; i--)
{
int c=((((ll)1<<i)&x)?1:0);
if(!tree[cp][p][c])
{
tree[cp][p][c]=++id[cp];
tree[cp][id[cp]][0]=tree[cp][id[cp]][1]=0;
}
p=tree[cp][p][c];
}
}
ll fond(int cp,ll x)
{
ll ret=0,p=0;
for(int i=32; i>=0; i--)
{
int c=((((ll)1<<i)&x)?1:0);
if(tree[cp][p][!c])
{
ret+=(ll)1<<i;
p=tree[cp][p][!c];
}
else
p=tree[cp][p][c];
}
return ret;
}
void dfs(ll now,int x,int y)
{
if(x+y==n+1)
{
updata(x,now^a[x][y]);
return;
}
dfs(now^a[x][y],x+1,y);
dfs(now^a[x][y],x,y+1);
}
void dfs1(ll now,int x,int y)
{
if(x+y==n+1)
{
ans=max(ans,fond(x,now));
return;
}
dfs1(now^a[x][y],x-1,y);
dfs1(now^a[x][y],x,y-1);
}
int 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]);
dfs(e,1,1);
dfs1(0,n,n);
printf("%lld
",ans);
return 0;
}