牛客練習賽 37 C 筱瑪的迷陣探險 【折半搜尋+01字典樹】

幾許情愁發表於2019-01-21

題目連結: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;
}


 

相關文章