思路
树形DP,首先是递归建树,然后是DP状态方程转移。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include <cmath>
#include<vector>
#define ll long long
#define inf 0x3f3f3f3f
#define maxn 500005
using namespace std;
struct Edge{
int v, next;
}edge[maxn];
int head[maxn], vis[maxn], cnt, n, m;
int dpmx[maxn][2], dpmi[maxn][2];
int nows = 0, nownode = 1;
char s[maxn];
void add_edge(int u, int v){
edge[cnt].v = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void build(int x){
++nows;
if(s[nows]=='1'){
add_edge(x, ++nownode);
build(nownode);
} else if(s[nows]=='0') return;
else{
add_edge(x,++nownode);
build(nownode);
add_edge(x,++nownode);
build(nownode);
}
}
void dfs(int u){
int du = 0;
int son1=0,son2=0;
for(int i = head[u]; i!=-1; i=edge[i].next){
int v = edge[i].v;
dfs(v);
du++;
if(!son1) son1 = v;
else son2 = v;
}
if(!du){
dpmx[u][0] = 0;dpmx[u][1] = 1;
dpmi[u][0] = 0;dpmi[u][1] = 1;
}
if(du==1){
dpmx[u][0] = max(dpmx[son1][0],dpmx[son1][1]);
dpmx[u][1] = dpmx[son1][0]+1;
dpmi[u][1] = dpmi[son1][0]+1;
dpmi[u][0] = min(dpmi[son1][0],dpmi[son1][1]);
}
if(du==2){
dpmx[u][0] = max(dpmx[son1][1]+dpmx[son2][0],dpmx[son2][1]+dpmx[son1][0]);
dpmx[u][1] = dpmx[son1][0]+dpmx[son2][0]+1;
dpmi[u][1] = dpmi[son1][0]+dpmi[son2][0]+1;
dpmi[u][0] = min(dpmi[son1][1]+dpmi[son2][0],dpmi[son2][1]+dpmi[son1][0]);
}
}
void init(){
memset(dpmx, -inf, sizeof(dpmx));
memset(dpmi, 0x3f, sizeof(dpmi));
cnt = 0;
memset(head, -1, sizeof(head));
}
int main(){
int i, j, k;
init();
scanf("%s",s+1);
build(1);
dfs(1);
printf("%d ",max(dpmx[1][0],dpmx[1][1]));
printf("%d\n",min(dpmi[1][0],dpmi[1][1]));
}