牛客练习赛37 C 筱玛的迷阵探险(Trie+折半)
生活随笔
收集整理的這篇文章主要介紹了
牛客练习赛37 C 筱玛的迷阵探险(Trie+折半)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:
筱瑪的迷陣探險
?
題意:
一個n×n的矩陣A,每個格子上有一個有一個數Ai,j。入口在左上角的(1,1)處,出口在右下角的(n,n)處。每一步都只能向下或向右移動一格。最后能獲得的經驗值為初始經驗e與路徑上經過的所有數的權值異或和。求筱瑪最大可能獲得的經驗值。
?
思路:
如果純暴力,dfs整張圖,復雜度O(2^(2n)),數量級最壞情況下為O(2^40),肯定會TLE。
但如果只暴力搜半張圖,最壞為O(2^20),時間沒有問題。因此,我們先從(1,1)開始dfs暴力遍歷上半張圖(上半部分,以對角線(從右上到左下)為分割線),對角線上的每個點開一棵字典樹,存到這個點的所有可能情況。然后我們再從(n,n)開始暴力遍歷下半張圖,每當搜到對角線上的點時就去該字典樹上求異或最大值(復雜度O(logk)= 31,k為字典樹節點個數),取所有最大值中的最大值。
總復雜度O(2^20 * logk)
注意:字典樹的空間大小盡可能大,這題有毒......
?
Code:
#include <bits/stdc++.h> using namespace std;typedef long long ll;const int MAX = 5e6+10;int n; ll e; ll mp[25][25]; int tree[25][MAX][2]; int tot=0; ll ans=0;void add(int id,ll x) {int root=0;for(int i=30;i>=0;i--){int p=(x>>i)&1;if(!tree[id][root][p]) tree[id][root][p]=++tot;root=tree[id][root][p];} }ll query(int id,ll x) {int root=0;ll val=0;for(int i=30;i>=0;i--){int p=(x>>i)&1;if(tree[id][root][p^1]){val+=(1ll<<i);root=tree[id][root][p^1];}else{root=tree[id][root][p];}}return val; }void dfs1(int x,int y,int step,ll val) {if(step==n){add(x,val^mp[x][y]);return;}if(y+1<=n) dfs1(x,y+1,step+1,val^mp[x][y]);if(x+1<=n) dfs1(x+1,y,step+1,val^mp[x][y]); }void dfs2(int x,int y,int step,ll val) {if(step==n){ans=max(ans,query(x,val));return;}if(y-1>=1) dfs2(x,y-1,step+1,val^mp[x][y]);if(x-1>=1) dfs2(x-1,y,step+1,val^mp[x][y]); }int main() {scanf("%d%lld",&n,&e);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%lld",&mp[i][j]);tot=0;ans=0;dfs1(1,1,1,e);dfs2(n,n,1,0);printf("%lld\n",ans);return 0; }?
總結
以上是生活随笔為你收集整理的牛客练习赛37 C 筱玛的迷阵探险(Trie+折半)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: fpu测试_仪器仪表 —— 一氧化碳测试
- 下一篇: QT自制秒表计时器、可获取电脑时间