题目链接:https://ac.nowcoder.com/acm/contest/342/C
题目:
筱玛是个快乐的男孩子。
寒假终于到了,筱玛决定请他的朋友们一起来玩迷阵探险。
迷阵可以看做一个n×n的矩阵A,每个格子上有一个数Ai,j。
入口在左上角的(1,1)处,出口在右下角的(n,n)处。每一步都只能向下或向右移动一格。最后能获得的经验值为初始经验e与路径上经过的所有数的权值异或和。
求筱玛最大可能获得的经验值。
输入:
第一行两个整数n和e。
接下来n行,每行n个整数,描述矩阵A。
输出:
一个整数,表示筱玛最大可能获得的经验值。
思路:直接搜索全部会超时,用折半搜索,对角线(坐下到右上)上的所有点当字典树树根,存从起点到对角线上的点的异或和的二进制,然后从终点搜到对角线上的所的点,找到最大值;
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<math.h>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const ll mod=1e8;
const int N=2;
const int M=22;
typedef struct Node
{
Node *Next[N];
}Node;
Node *tre[M];
int mp[M][M];
int n,e,ans;
Node * build()//建立根节点
{
Node *node=(Node *)malloc(sizeof(Node));
node->Next[0]=node->Next[1]=0;
return node;
}
void tree_insert(Node *root,int x)//插入二进制
{
int t,i=30;
Node *p=root;
while(i>=0)
{
t=(x>>i)&1;
if(p->Next[t]==NULL)
p->Next[t]=build();
p=p->Next[t];
i--;
}
}
int tree_query(Node *root,int x)//寻找异或和最大的
{
int res=0,t,i=30;
Node *p=root;
while(i>=0)
{
t=(x>>i)&1;
if(p->Next[t^1]!=NULL)
{
res|=(1<<i);
t^=1;
}
p=p->Next[t];
i--;
}
return res;
}
void dfs1(int x,int y,int sum)//深搜从(0,0)到对角线(左下角到右上角)上的所有点
{
if(x+y==n-1)
{
sum^=mp[x][y];
tree_insert(tre[x],sum);
return;
}
dfs1(x+1,y,sum^mp[x][y]);
dfs1(x,y+1,sum^mp[x][y]);
}
void dfs2(int x,int y,int sum)//深搜从终点到对角线上的所有点
{
if(x+y==n-1)
{
ans=max(tree_query(tre[x],sum),ans);
return;
}
dfs2(x-1,y,sum^mp[x][y]);
dfs2(x,y-1,sum^mp[x][y]);
}
int main()
{
while(~scanf("%d %d",&n,&e))
{
for(int i=0;i<n;i++)
tre[i]=build();
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&mp[i][j]);
ans=0;
dfs1(0,0,e);
dfs2(n-1,n-1,0);
printf("%d\n",ans);
}
return 0;
}