Question Link: Https://vijos.org/p/1100
Theme: Noip is a famous extra binary tree. Returns a tree's ordinal traversal. The left subtree * The right subtree + the root are added to the rule. The empty subtree score is 1. Ask the tree structure with the maximum extra points, and traverse the output tree first.
Solutions:
First, let's look at it from an early perspective.
As long as you know what the root is, you can easily find the bonus points of a subtree.
Then it becomes the interval DP problem of enumeration root.
To output first-order traversal, use M [I] [J] to record ~ The root of the J interval.
Interval DP boundary:
① Point: no left and right subtree, DP [I] [I] = node [I], M [I] [I] = I.
② There are two vertices, that is, no right subtree. DP [I] [I + 1] = node [I] + node [I + 1]; m [I] [I + 1] = I.
Note that the DP boundary is two cases, because the left and right intervals are processed according to the general procedures when the interval DP enumeration is in the middle Split points. In the above two cases, there are problems in the left and right intervals.
Therefore, special preprocessing is required.
Interval DP:
We recommend that you first write the enumeration interval P, which is calculated directly from P = 2. P = 0, P = 1 has been preprocessed.
For DP [I] [J], the range of root K (I + 1, J) is enough to write the equation according to the rule. M [I] [J] = K, which records the root of each interval.
Then the last ans = DP [1] [N].
Recursive print scheme. First, traverse the left and right of the root in order. Do not make any mistake.
#include "cstring"#include "cstdio"#include "cstring"int dp[31][31],m[31][31],node[31];void print(int i,int j){ printf("%d ",m[i][j]); if(i<=m[i][j]-1) print(i,m[i][j]-1); if(m[i][j]+1<=j) print(m[i][j]+1,j);}int main(){ //freopen("in.txt","r",stdin); int n; while(scanf("%d",&n)!=EOF) { memset(dp,0,sizeof(dp)); for(int i=1; i<=n; i++) scanf("%d",&node[i]); for(int i=1; i<=n; i++) { dp[i][i]=node[i]; m[i][i]=i; dp[i][i+1]=node[i]+node[i+1]; m[i][i+1]=i; } for(int p=2; p<=n; p++) { for(int i=1; i<=n; i++) { int j=i+p; if(j>n) break; dp[i][j]=1; for(int k=i+1; k<j; k++) { if((dp[i][k-1]*dp[k+1][j]+node[k])>dp[i][j]) { dp[i][j]=dp[i][k-1]*dp[k+1][j]+node[k]; m[i][j]=k; } } } } printf("%d\n",dp[1][n]); print(1,n); }}
Vijos 1100 (interval DP)