DP专题考试总结(2)
来源:互联网 发布:网络诈骗300元立案吗 编辑:程序博客网 时间:2024/06/16 21:32
最近努力学(tui)习(fei)了DP专题,然后就被烤焦了,然后就没有然后了。
对此,我只想说——
DP made me Boom-Sha-Ka-La-Ka
加分二叉树
期望得分:0
实际得分:0
Description
设一个n个节点的二叉树tree的中序遍历为(l,2,3,…,n),其中数字1,2,3,…,n为节点编号。每个节点都有一个分数(均为正整数),记第j个节点的分数为di,tree及它的每个子树都有一个加分,任一棵子树subtree(也包含tree本身)的加分计算方法如下:
subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数
若某个子树为主,规定其加分为1,叶子的加分就是叶节点本身的分数。不考虑它的空
子树。
试求一棵符合中序遍历为(1,2,3,…,n)且加分最高的二叉树tree。要求输出;
(1)tree的最高加分
(2)tree的前序遍历
现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。
Data Size
n<=30
分数<=100
思路
考试的时候,看完了题就开始懵了。诶?这么复杂?难道要用什么变态的算法。
然后我就果断地跳了题。后来发现因为数据过水,100分很容易拿,跳了真是可惜了。
有点类似一道区间DP的题目。
这里用f[rt][l][r]表示[l,r]段以rt为根节点的最优加分二叉树,然后记忆化搜索。
感觉整个程序打下来,充斥着暴力的气息,全都是暴力枚举、暴力更新……本人过于蒟蒻,程序毫无技术可言,成功地1ms水了过去。
代码
#include <iostream>#include <cstring>#include <cstdio>using namespace std;typedef long long ll;const int size=35;int n,rt[size][size],ans[size][size];ll tot,score[size],f[size][size][size];inline ll dfs(int now,int l,int r){ if(f[now][l][r]!=-1) return f[now][l][r]; if(l==r) { f[now][l][r]=score[l]; rt[l][r]=l; return f[now][l][r]; } ll lc=0,rc=0,t; for(int i=l;i<now;i++)//暴力枚举根节点,下同 if(lc<(t=dfs(i,l,now-1))) { lc=t; rt[l][now-1]=i; } for(int i=now+1;i<=r;i++) if(rc<(t=dfs(i,now+1,r))) { rc=t; rt[now+1][r]=i; } if(!(l<=now-1)) lc=1; if(!(now+1<=r)) rc=1; f[now][l][r]=lc*rc+score[now]; return f[now][l][r];}inline void print(int l,int r)//按照记录的路径进行前序遍历输出{ int now=ans[l][r]; printf("%d ",now); if(l<=now-1) print(l,now-1); if(now+1<=r) print(now+1,r);}int main(){ memset(f,-1,sizeof(f)); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&score[i]); for(int i=1;i<=n;i++) { ll t=dfs(i,1,n); if(t>tot)//如果搜到了更优的结果就暴力更新记录的路径 { tot=t; rt[1][n]=i; for(int j=1;j<=n;j++) for(int k=j;k<=n;k++) ans[j][k]=rt[j][k]; } } printf("%lld\n",tot); print(1,n); return 0;}
凸多边形的三角剖分
期望得分:100
实际得分:100
Description
给定一具有 N 个顶点(从 1 到 N 编号)的凸多边形,每个顶点的权均已知。问如何把
这个凸多边形划分成N-2个互不相交的三角形,使得这些三角形顶点的权的乘积之和最小?
Date Size
N<50
每个顶点的权值<32768
思路
乍一看题目,似乎是什么特别高深的问题,后来仔细一下,其实是一道区间DP的水题。
f[l][r]就表示对于区间[l,r]的最优答案。
代码
#include <iostream>#include <cstdio>using namespace std;typedef long long ll;const int size=55;ll n,a[size],f[size][size];int main(){ scanf("%lld", &n); for(int i=1; i<=n; i++) scanf("%lld", &a[i]); for(int i=0;i<=n;i++)//初始化 { f[i][i]=a[i]; f[i][i+1]=0; for(int j=i+2;j<=n;j++) f[i][j]=(ll)32767*32767*32767; } for(int i=n;i>=1;i--) for(int j=i+2;j<=n;j++) for(int k=i+1;k<=j-1;k++)//枚举断点 f[i][j]=min(f[i][j],f[i][k]+f[k][j]+a[i]*a[j]*a[k]); printf("%lld\n",f[1][n]); return 0;}
火车进站 (不可做)
期望得分:0
实际得分:0
Description
火车站内往往设有一些主干线分叉出去的铁路支路,供火车停靠,以便上下客或装载货物。铁路支路有一定长度;火车也有一定的长度,且每列火车的长度相等。
假设某东西向的铁路上,有一小站。该站只有一条铁路支路可供火车停靠,并且该铁路支路最多能容纳M 辆火车。为了火车行驶的通畅,该站只允许火车自东方进站,自西方出站,且先进站的火车必须先出站,否则,站内火车将发生堵塞。该火车站工作任务繁忙。每天都有 N 辆自东方驶向西方的火车要求在预定时刻进站,并在站内作一定时间的停靠。
为了满足每辆进站火车的要求,小站的调度工作是井井有条地开展。在小站每天的工作开始前,小站工作人员须阅读所有火车的进站申请,并决定究竞接受哪些火车的申请。而对于不能满足要求的火车,小站必须提前通知它们,请它们改变行车路线,以免影响正常的铁路运输工作。由于火车进站、出站的用时可以忽略不计,小站允许几辆火车同时进站或出站,且小站工作人员可以任意安排这些火车进站的先后排列次序。小站的工作原则是尽量地满足申请火车的要求。
请你编一个程序,帮助工作人员考察某天所有火车的进站申请,计算最多能满足多少火车的要求。
Date Size
N<=100;
M<=3;
思路
这题需要分类讨论,耗时不AC。果断认定不可做,跳题。
状态转移方程:
m=1:f[i]=max(f[j]+1);
m=2:f[i][j]=max(f[k][i]+1);(k
最长前缀 (不可做)
至今未做,据说要用kmp算法,留此坑以后再填……
- DP专题考试总结(2)
- DP专题考试总结(4)
- 专题三总结,DP
- dp专题总结
- 数位DP专题总结
- 算法专题:DP(2)
- 本次考试总结(2017.9.2考试)
- 逊哥dp专题 总结(普通dp,斜率优化dp,数位dp)
- 【专题总结】概率&期望DP
- dp专题2--简单dp
- 专题(弱点)Dp训练总结【状压Dp*1+区间Dp*5+数位dp*3+树型Dp*2】【10/11】
- 数位dp初等专题小总结
- 【DP_树形DP专题】题单总结
- 通过考试(概率dp)
- 考试总结2
- 20191021考试总结2
- 暑假训练2-DP专题
- dp 系列专题(三)
- (M)Dynamic Programming:392. Is Subsequence
- 利用dlib库(Python)实现实时(摄像头)人脸检测以及特征点标定(landmark))
- 链式前向星
- CSS学习笔记—CSS的引入方式
- 转载:caffe学习:多平台下安装配置caffe
- DP专题考试总结(2)
- <c语言经典100例>c25 递归输出1-100
- Hou Yi's secret(hdu4082——2011icpc北京站B题)
- leetcode 331. Verify Preorder Serialization of a Binary Tree 二叉树的前序序列验证
- 小白的第一篇博客
- java内部类
- 解决Visual Studio编译错误"文本后缀无效; 未找到文文本运算符或文本运算符模板"
- 贪心法 求最大子阵列
- 51nod 1837 砝码称重