牛客练习赛37

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;
}

  

原文地址:https://www.cnblogs.com/SDUTNING/p/10258890.html