【Luogu】P1040加分二叉树(区间DP)
区间DP,因为中序遍历的性质:区间[l,r]的任何一个数都可以是该区间的根节点。
更新权值的时候记录区间的根节点,最后DFS输出。
见代码。
#include<cstdio> #include<cctype> #include<algorithm> inline long long max(long long a,long long b){ return a>b?a:b; } inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } long long f[500][500]; int rt[500][500]; int que[500]; void dfs(int x,int y){ printf("%d ",rt[x][y]); if(rt[x][y]>x) dfs(x,rt[x][y]-1); if(rt[x][y]<y) dfs(rt[x][y]+1,y); } int main(){ int n=read(); for(int i=1;i<=n;++i){ f[i][i]=que[i]=read(); rt[i][i]=i; } for(int l=2;l<=n;++l) for(int i=1;i+l-1<=n;++i){ int j=i+l-1; for(int k=i;k<=j;++k){ long long L=f[i][k-1],R=f[k+1][j]; if(k==i&&k!=j) L=1; if(k==j&&k!=i) R=1; if(f[i][j]<L*R+f[k][k]){ rt[i][j]=k; f[i][j]=L*R+f[k][k]; } } } printf("%lld\n",f[1][n]); dfs(1,n); return 0; }