noip2003加分二叉树
因为一开始给出的是中序遍历 所以这其实是一道区间dp。。。
dp的同时记一下每个点的儿子就可以完成第二问
#include<iostream> #include<cstdio> using namespace std; int a[32],n,f[32][32],crf[32][32]; long long work(int l,int r) { int k; if (crf[l][r]) return crf[l][r]; if (l>r) return 1; if (l==r) return a[l]; long long res=0,temp=0; int root=0; for (k=l;k<=r;k++) {temp=work(l,k-1)*work(k+1,r)+a[k]; if (temp>res) {res=temp;root=k;} crf[l][r]=res; f[l][r]=root;} return res; } void doit(int l,int r) { if (l>r) return; if (l==r) {cout<<l<<' ';return;} int root=f[l][r]; cout<<root<<' '; doit(l,root-1); doit(root+1,r); } int main() { cin>>n; for (int i=1;i<=n;i++) cin>>a[i]; cout<<work(1,n)<<endl; doit(1,n); }