P1040 加分二叉树
https://www.luogu.com.cn/problem/P1040
n很小,可以树形dp或者区间dp。
设fij为从i到j的最大加分值,则有f[i][j]=max(f[i][k-1]*f[k+1][j]+f[k][k])。
有一个小技巧,将f[i][i-1]全部设置为1,这样的话搜索到叶子就也可以按照通式dp了。
对于输出前序遍历(根,左树,右树)我们再树形dp一下就行了。
树形dp比较清晰明了(但是耗内存)。不想写树形dp的话递推式如上。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 inline int read() 7 { 8 int x=0,w=1;char c=getchar(); 9 while(!isdigit(c)){ 10 if(c=='-')w=-1; 11 c=getchar(); 12 } 13 while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar(); 14 return x*w; 15 } 16 const int maxn=35; 17 int n; 18 int f[maxn][maxn],a[maxn],ro[maxn][maxn]; 19 int search(int l,int r) 20 { 21 if(l>r)return 1; 22 if(l==r){ro[l][r]=l;return f[l][r];} 23 if(f[l][r])return f[l][r]; 24 for(int w,i=l;i<=r;i++) 25 { 26 w=search(l,i-1)*search(i+1,r)+f[i][i]; 27 if(w>f[l][r])f[l][r]=w,ro[l][r]=i; 28 } 29 return f[l][r]; 30 } 31 void print(int l,int r) 32 { 33 if(l>r)return ; 34 printf("%d ",ro[l][r]); 35 print(l,ro[l][r]-1); 36 print(ro[l][r]+1,r); 37 } 38 int main() 39 { 40 n=read(); 41 for(int i=1;i<=n;i++)f[i][i]=read(); 42 search(1,n); 43 printf("%d\n",f[1][n]); 44 print(1,n);//发扬先辈遗德,恢弘志士之气 45 return 0; 46 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现