ZJOI2016 三色二叉樹
阿新 • • 發佈:2018-11-11
首先 此題給出的時一個可以代表二叉樹的一個序列
直接遞迴把樹建出來就好了。
然後考慮DP。
比較容易想到的是一個f[i][3]的DP,分別代表以i為根時,i染三種顏色的最大數目。
直接根據限制轉移即可,但程式碼比較長。
考慮(程式碼)簡單一點的,
實際上,由於我們只在意綠色的染了多少,所以染其他兩種色沒有區別(也就是可以完全互相轉換)。
所以考慮是否可以設f[i][2],分別代表以i為根時,i染或不染綠色的最大數目。
同樣直接根據限制轉移。
#include <bits/stdc++.h> #define LL long long using namespacestd; const int MAXN=5e5+10; char Tr[MAXN]; int Id,Cnt,tot,head[MAXN],Son[MAXN][3],Min[MAXN][2],Max[MAXN][2]; void Build (int Nx) { Son[Nx][0]=Tr[++Cnt]-'0'; if (!Son[Nx][0]) return; for (int i=1;i<=Son[Nx][0];++i) { Son[Nx][i]=++Id; Build (Id); } } void Tr_DP (int Nx) {for (int i=1;i<=Son[Nx][0];++i) Tr_DP (Son[Nx][i]); if (Son[Nx][0]==0) { Min[Nx][1]=Max[Nx][1]=1; return; } else if (Son[Nx][0]==1) { int Nex=Son[Nx][1]; Min[Nx][1]+=Min[Nex][0]+1; Max[Nx][1]+=Max[Nex][0]+1; Min[Nx][0]=min (Min[Nex][0], Min[Nex][1]); Max[Nx][0]=max (Max[Nex][0], Max[Nex][1]); } else { int Nex1=Son[Nx][1], Nex2=Son[Nx][2]; Min[Nx][1]+=Min[Nex1][0]+Min[Nex2][0]+1; Max[Nx][1]+=Max[Nex1][0]+Max[Nex2][0]+1; Min[Nx][0]=min (Min[Nex1][0]+Min[Nex2][1], Min[Nex1][1]+Min[Nex2][0]); Max[Nx][0]=max (Max[Nex1][0]+Max[Nex2][1], Max[Nex1][1]+Max[Nex2][0]); } } int main () { scanf ("%s", Tr+1); Build (++Id); Tr_DP (1); printf ("%d %d\n", max (Max[1][0], Max[1][1]), min (Min[1][0], Min[1][1]) ); return 0; }