时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld
题目描述
筱玛是个快乐的男孩子。
寒假终于到了,筱玛决定请他的朋友们一起来玩迷阵探险。
迷阵可以看做一个n×nn×n的矩阵A,每个格子上有一个有一个数Ai,j。
入口在左上角的(1,1)处,出口在右下角的(n,n)处。每一步都只能向下或向右移动一格。最后能获得的经验值为初始经验e与路径上经过的所有数的权值异或和。
求筱玛最大可能获得的经验值。
输入描述:
第一行两个整数n和e。 接下来n行,每行n个整数,描述矩阵A。
输出描述:
一个整数,表示筱玛最大可能获得的经验值。
示例1
输入
复制
5 2 3 4 7 2 6 3 5 2 9 0 3 8 5 7 3 2 5 3 1 4 9 8 6 3 5
输出
复制
15
备注:
1≤n≤20;0≤e,Ai,j<231
地址:https://ac.nowcoder.com/acm/contest/545/D
思路:折半DFS+01字典树
这题用纯DFS会超时,但是从左上到右下一定会经过对角线(x,x)的位置,因此可以从左上,右下两端搜到对角线(x,x)的位置,再用01字典树求出异或最大值即可
Code:
#include<iostream>
using namespace std;
const int MAX_N=25;
const int MAX_S=3200005;
int n,e,ans;
int a[MAX_N][MAX_N];
int Trie[MAX_N][MAX_S][2],num[MAX_N];
void Insert(int x);
int Query(int x);
void DFS1(int k,int s,int Sum);
void DFS2(int k,int s,int Sum);
int main()
{
ios::sync_with_stdio(false);
cin>>n>>e;
for(int i=1;i<=n;++i)
for(int j=1,x;j<=n;++j)
cin>>a[i][j];
DFS1(1,1,e);
DFS2(n,n,0);
cout<<ans<<endl;
return 0;
}
void Insert(int k,int x)
{
int u=0,t;
for(int i=31;i>=0;--i)
{
t=(x>>i)&1;
if(!Trie[k][u][t]) Trie[k][u][t]=++num[k];
u=Trie[k][u][t];
}
}
int Query(int k,int x)
{
int t,u=0,res=0;
for(int i=31;i>=0;--i)
{
t=(x>>i)&1;
if(Trie[k][u][!t]) res|=(1<<i),u=Trie[k][u][!t];
else u=Trie[k][u][t];
}
return res;
}
void DFS1(int k,int s,int Sum)
{
if(k>n) return;
if(k+s>n+1) return;
if(k+s==n+1){
Insert(k,Sum^a[k][s]);
return;
}
int pp=0;
for(int i=s;i<=n-k+1;++i)
{
pp^=a[k][i];
DFS1(k+1,i,Sum^pp);
}
Insert(k,Sum^pp);
}
void DFS2(int k,int s,int Sum)
{
if(k<1) return;
if(k+s<n+1) return;
if(k+s==n+1){
ans=max(ans,Query(k,Sum));
return;
}
int pp=0;
for(int i=s;i>=n-k+1;--i)
{
pp^=a[k][i];
DFS2(k-1,i,Sum^pp);
}
Sum^=pp^a[k][n-k+1];
ans=max(ans,Query(k,Sum));
}