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\n",ans); return 0; }