P5597 【XR-4】復讀 思維題 +二叉樹合併
阿新 • • 發佈:2020-10-21
題意:
分析:
由於這是一個無限大的完全二叉樹,所以不合法的方案僅存在於跳到根節點的父親這一種,且由於指令會無限重複,所以我們必須保證指令會使得離開被標記的子樹的時候,所有被標記的點已經全部訪問完,因為我們不會折返回去向上跳的
那麼我們考慮列舉它是經過哪條路徑,從哪個點離開整顆子樹的,只要保證在走這條路經的同時遍歷完所有的點,且由於指令會無限重複,所以我們對於路徑上每一個點,將所有的子樹求一個形態上的並集,只要使得整個並集能被訪問,那麼所有的點都會被訪問到,最後的答案就是\((cnt-1)*2-dep\),其中\(cnt\)是並集的樹上節點數,\(dep\)為我們列舉的離開的點的深度
程式碼:
#include<bits/stdc++.h> using namespace std; namespace zzc { const int maxn = 2e3+5; int ans=1e9+7,cnt,cur,rt,pos; char ch[maxn],pth[maxn]; struct tree { int lc,rc; }f[maxn],g[maxn]; void build(int &x) { if(!x) x=++cnt; int t=ch[pos++]-'0'; if(t&1) build(f[x].lc); if(t&2) build(f[x].rc); } void merge(int &x,int y) { if(!x) x=++cnt; if(y==cur) return ; if(f[y].lc) merge(g[x].lc,f[y].lc); if(f[y].rc) merge(g[x].rc,f[y].rc); } void solve(int u,int dep) { if(u!=1) { memset(g,0,sizeof(g)); cur=cnt=1; while(cur) { const int t=cur; for(int i=0;i<dep;i++) { cur=pth[i]=='l'?f[cur].lc:f[cur].rc; } merge(rt=1,t); } ans=min(ans,(cnt-1)*2-dep); } pth[dep]='l'; if(f[u].lc) solve(f[u].lc,dep+1); pth[dep]='r'; if(f[u].rc) solve(f[u].rc,dep+1); } void work() { scanf("%s",ch);pos=0;cnt=1; build(rt=1); solve(1,0); printf("%d\n",ans); } } int main() { zzc::work(); return 0; }