2019暑训8月9号 dp入门选讲

VJ

题目链接
A
区间dp:定义dp[x][y]为从顶点x到顶点y之间最小的三角划分,枚举中间的每一个点k,有递推关系:
dp[x][y] = min(dp[x][y], dp[x][k] + dp[k][y] + x * k * y);
注意一些细节比如长度y - x的范围、dp数组的初始化问题。
数学规律: 可以验证的是,每次新添一个点n + 1,只需要把它与1与n相连就可以保证这是一个最小三角划分。具体证明我不会
我是∈的…zxt同学提醒了我我在某场cf打过这道题并且用数学办法秒了后我还是记得不是很真切…当时怎么就想得到这样做呢…(迷惑

C
这道题想了很久…最开始是顺从知识点考虑用区间dp,定义了dp[x][y]为攻击完x到y的狼后受到的最下伤害,枚举k为最先攻击的狼的序号…搞了半天发现是算法假了…后来又想用数学办法考虑…(因为注意到初始攻击力是抗且仅抗一下的,但是附加伤害可能会形成某种隐蔽的数学关系?)…最后还是搞不出来
然后屈从于找题解了 与我最开始的转移办法不同的是,标答应该是枚举最后攻击的狼的序号,这样子可以把x - 1和y + 1带来的附加伤害做一个有效的处理。真的很有道理…但是我当时想不到…

B
除凸包这一新知识点以外,dp的设置与转移与A类似。
这里我们讨论一下判断平面上的散点能否构成凸包的办法。
凸包问题的五种解法
网上的博客基本都是在讲述散点中如何构造出最大的凸包,但是从中也可以发现一些一般性的办法。我们先找到最左下角的点,之后把剩余的点进行极角排序。值得一提的是,如果使用浮点数对斜率进行排序有点得不偿失,可以直接根据叉乘的符号进行排序,避免了浮点数的除法从而保证了精度。极角排序完成后,point数组存储的点就是该多边形逆时针排序的点。考虑到该题的范围,直接O(N3)暴力检查某条边是否在其他所有点的同一侧即可。

D
该开始做区间dp的时候算法假了,难以做到不重不漏的进行状态转移。之后用了完全背包先预处理了n个相同的数可以获得的最大point后打算暴力dp…感觉还是dp转移的有问题…
Codeforces 1107E. Vasya and Binary String(DP) (这篇博客比较好看)
定义dp数组dp[i][j][k]是消除区间i到j以及与s[j]相同且恰在其之后连续的k个相同元素所获得的最大point。
这里的k个连续元素放在之前或者之后是类似的,我选择了放在后面。
在这里插入图片描述
本来想用循环写出来,无奈码力不足…参见聚聚博客用记忆化+递归处理了这个问题。 在这个solve函数中,有几点困扰我许久:
1.状态方程的转移: 可以通过行43的代码注释看出之前对该转移的错误理解。事实上,行44的转移方程是将某一段消除后,可以将目前的后缀增广,从而不断的减小xy增大k递归求解。

2.终止条件以及边界问题:最开始搞的时候因为要顾及solve(i + 1, y - 1, 0)就在终止条件中设置了y == x + 1, y == x + 2这些丑陋的条件…事实上,我们只需要加上行39就可以了。这是因为,出现x > y的状况只有可能是因为solve(i + 1, y - 1, 0)而产生,更具体的说,也就是i恰好等于y - 1。这个时候,前面的solve(x, i, k + 1)的表达没有问题,让后面的solve返回0就正好符合题意而又干净漂亮了!

3.是否需要完全背包?上述题解博客将我这里的cont(表示连续n个数最大可以获得分数)全部直接换成了题目直接输入的那一行数据…我直观的感觉他是错的,只是3 4 9 100 …没卡住他,我换成了3 4 9 2…后他的答案还是与我的吻合…这意味着他这样子搞也是正确的。仔细考虑后可以发现,其实这一套递归办法已经遍历了所有的情况,那么也就都已经完全没有遗漏地考虑了擦除的不同方法,所以使用完全背包有点多此一举画蛇添足了…

F
定义dp[i][0]为在以i为根的子树中结点i 不去 时最多的权值, dp[i][1]为在以i为根的子树中结点i 时最多的权值。从而容易有转移方程:
dp[i][0] += max{dp[j][0], dp[j][1] *[j是i的儿子结点]}
dp[i][1] += dp[j][0] * [j是i的儿子结点]

G
假dp真贪心
显然的,对于一个结点,如果它所有的儿子都是叶子,那么这个结点必定要染色。而染色点所连的所有边都无需再守卫了,我们直接删去这些边即可。为此,我们给每一条边设置两个访问变量。一个用来记录这条边是否被删去,一个用来记录访问情况来完成dfs。每当完成一次dfs后,检查前一个访问数组是否全部被删除,如果没有,重置第二个访问数组再进行一次dfs,反复上述操作直到前一个数组全部标记为TRUE。
G题AC代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值