链接:
https://ac.nowcoder.com/acm/contest/342/C
来源:牛客网
题目描述
筱玛是个快乐的男孩子。
寒假终于到了,筱玛决定请他的朋友们一起来玩迷阵探险。
迷阵可以看做一个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
思路
折半,字典树。
从左上角遍历到对角线停止,用字典树存对角上每个点的所有可能值。
再从右下角往对角线遍历,到对角线时,贪心找字典树上每位数都为1的值,再异或算答案
有人说注意字典树大小
代码
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <sstream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iomanip>
#include <stack>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int N = 5e6 + 50;
const int MOD = 1e9 + 9;
#define lson l, m, rt << 14
#define rson m + 1, r, rt << 1 | 1
#define F(i, l, r) for(int i = l;i <= (r);++i)
#define RF(i, l, r) for(int i = l;i >= (r);--i)
int n;
LL mp[30][30], ans, e;
int tree[30][N][2], cnt;
void Add(int id, LL num)
{
int rt = 0;
RF(i, 30, 0)
{
int t = (num >> i) & 1;
if(!tree[id][rt][t]) tree[id][rt][t] = ++cnt;//这里写成cnt++就错了,注意字典树模板
rt = tree[id][rt][t];
}
}
LL solve(int id, LL num)
{
LL rt = 0, ret = 0;
RF(i, 30, 0)
{
int t = (num >> i) & 1;
if(tree[id][rt][t ^ 1]) {ret += (1ll << i);rt = tree[id][rt][t ^ 1];}
else rt = tree[id][rt][t];
}
return ret;
}
void dfs1(int x, int y, LL val)
{
if(x + y == n + 1) {Add(x, val ^ mp[x][y]);return ;}
if(y + 1 <= n) dfs1(x, y + 1, val ^ mp[x][y]);
if(x + 1 <= n) dfs1(x + 1, y, val ^ mp[x][y]);
}
void dfs2(int x, int y, LL val)
{
if(x + y == n + 1) {ans = max(ans, solve(x, val));return ;}
if(y - 1 > 0) dfs2(x, y - 1, val ^ mp[x][y]);
if(x - 1 > 0) dfs2(x - 1, y, val ^ mp[x][y]);
}
int main()
{
cin >> n >> e;
F(i, 1, n) F(j, 1, n) cin >> mp[i][j];
dfs1(1, 1, e);dfs2(n, n, 0);
cout << ans << endl;
return 0;
}