写在前面

记录最近刷的DP题 以及 打死都不可能想到状态设计DP系列 汇总

洛谷 P6082 [JSOI2015]salesman

树形\(\texttt{DP}\) + 优先队列

比较容易看出来这是一道树形\(\texttt{DP}\)题

要注意的是最大停留次数为输入次数-1,因为还要从子树返回到这一个节点

然后下面考虑怎么\(\texttt{DP}\)

我们用\(f[i]\)表示以从\(i\)出发,访问以\(i\)为根的子树,并且最后能回到\(i\)的最大收益

显然我们要选较大且非负的数,因为去大点权的节点肯定比去小点权的点权更优,去非负点权的节点肯定比去负点权的节点更优,而且因为一个节点可以去多次且只记一次点权,所以肯定能够用完次数,因此我们每次在小于等于停留次数的前提下取完正儿子即可,这样就可以保证最大,所以\(f[i]\)就等于\(i\)所有正儿子的点权之和(前提是小于等于最大停留次数),最后的答案就是\(f[1]\)

下面来考虑解是否唯一的问题,解不唯一有两种情况:

  1. \(i\)的子树中有权值为\(0\)的点。因为选不选权值都不变,所以可选可不选,因此解就不唯一了
  2. 如果\(i\)在遍历过程中当父亲节点剩余的停留次数为\(1\)时,可选的最大值有两个及两个以上儿子节点,则解不唯一

所以在过程中判断一下就好了

代码见洛谷 P6082 [JSOI2015]salesman

洛谷 P2831 愤怒的小鸟

未优化

状压\(\text{DP}\)

\(n\leq 18\),不是暴搜就是状压,因为我\(jio\)得状压会比较好理解,所以就写一篇状压的题解叭

首先我们要预处理出经过任意两点的抛物线可以击中的小猪有哪些,可以用\(line[i][j]\)来表示经过\(i,j\)的抛物线经过的小猪的集合,集合用二进制数来表示

  • 这里有一个小问题就是如何求抛物线\(y=ax^2+bx\)中的\(a,b\)

    假设目前的抛物线经过\((x_1,y_1)\)和\((x_2,y_2)\)两点,已知\(x>0\),那么有

    \[y_1=ax_1^2+bx_1
    \]

    \[y_2=ax_2^2+bx_2
    \]

    \[ax_1+b=\frac{y_1}{x_1}
    \]

    \[ax_2+b=\frac{y_2}{x_2}
    \]

    两式做差得

    \[a(x_1-x_2)=\frac{y_1}{x_1} - \frac{y_2}{x_2}
    \]

    所以

    \(a=\frac{\frac{y_1}{x_1} - \frac{y_2}{x_2}}{(x_1-x_2)}\)

    \(b=\frac{y_1}{x_1}-a*x_1\)

处理完之后就要想一想如何\(\text{DP}\)

我们设\(dp[s]\)表示消灭集合\(s\)内所有小猪所用的最少的小鸟数

显然\(dp[0]=0\),因为没有猪当然用不到鸟

假设当前的状态为\(s\),抛物线为经过\(i,j\)点的抛物线,这条抛物线打掉的小猪的状态为\(line[i][j]\),那么有

\[dp[s|line[i][j]] = \min(dp[s|line[i][j]],dp[s] + 1)
\]

其中\(s|line[i][j]\)表示当前状态\(s\)在增加了经过\(i,j\)点的这条抛物线之后能打到的小猪的集合,显然要从\(dp[s|line[i][j]]\)和\(dp[s]+1\)中取最小

时间复杂度\(O(Tn^22^n)\)O(能过才怪),在洛谷上吸氧(\(O2\))可以过

优化

随意选择\(s\)内的一只小猪\(j\),那么\(j\)最后一定会被一只小鸟消灭,所以我们固定住这只小猪\(j\),只枚举\(k\)转移

更详细见AThousandSuns的题解

时间复杂度\(O(Tn2^n)\),稳了

代码见洛谷 P2831 愤怒的小鸟

洛谷 P4910 帕秋莉的手环

题意

多组数据,给出一个环,要求不能有连续的\(1\),求出满足条件的方案数

\(1\le T \le 10, 1\le n \le 10^{18}\)

思路

20pts

暴力枚举(不会写

60pts

假设金珠子为\(0\),木珠子为\(1\),则不能有连续的木珠子

线性递推\(DP\),设\(f[i][0/1]\)表示当前填到第\(i\)位,第\(i\)位为金珠子/木珠子的方案数,那么有:

\[f[i][0] = f[i - 1][0] + f[i - 1][1]
\]

\[f[i][1] = f[i-1][0]
\]

但是要分成两种情况讨论

  • 第一个位置是\(0\),则\(f[1][0]=1,f[1][1]=0\),那么最后一个位置可以是\(0\)也可以是\(1\)

    所以此时对答案的贡献为\(f[n][0]+f[n][1]\)

  • 第一个位置是\(1\),则\(f[1][1]=1,f[1][0]=0\),那么最后一个位置只能是\(0\)

    所以此时对答案的贡献为\(f[n][0]\)

时间复杂度\(O(Tn)\),期望得分\(60\)分

不知道为什么,也许是我写假了,只有48分

100pts

考虑用矩阵优化,目前的状态为\([f_{i,0},f_{i,1}]\),目标状态为\([f_{i+1,0},f_{i+1,1}]\),比较容易推出转移矩阵为

\[[f_{i,0},f_{i,1}] * \left[ \begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix} \right] = [f_{i+1,0},f_{i+1,1}]
\]

按照\(60\)分做法写矩阵快速幂就好了

代码见洛谷 P4910 帕秋莉的手环

51Nod 1327 棋盘游戏

以行为状态转移无法记录各列的状态,所以以列为状态转移

设\(f[i][j][k]\)为处理到第\(i\)列,前面有\(j\)列没有填棋子,有\(k\)行已经填到了右区间的方案数

记\(l[i],r[i],mid[i]\)分别为左区间右端点为\(i\)的行数、右区间左端点为\(i\)的行数、第\(i\)列没有被左右区间覆盖的行数

每次到达左区间右端点的限制\(l_{i}\)时,再考虑如何满足这些左区间,则有如下三种转移:

  • 放在左区间内,就要满足将\(l_{i+1}\)行安排到前面没放棋子的\(j\)列中,因为顺序没有要求,所以直接乘上排列数,转移为

    \[f[i+1][j+1-l_{i+1}][k+r_{i+1}]+=f[i][j][k]\times A_{j+1}^{l_{i+1}}
    \]

  • 放在右区间内,要乘上左右两侧的方案数

    \[f[i+1][j-l_{i+1}][k+r_{i+1}-1]+=f[i][j][k]\times A_{j}^{l_{i+1}}\times (k+r_{i+1})
    \]

  • 放在未被覆盖的中间位置,要乘上左侧和中间的方案数

    \[f[i+1][j-l_{i+1}][k+r_{i+1}]+=f[i][j][k]\times mid_{i+1}\times A_{j}^{l_{i+1}}
    \]

初始状态为\(f[0][0][0]=1\),最后的答案为\(\sum_{i=1}^{m}f[m][i][0]\)

代码见51Nod 1327 棋盘游戏

51Nod 1683 最短路

题意

给定一个未知的\(0/1\)矩阵,对每个\(i\)求\((1,1)\sim(n,m)\)最短路为\(i\)的概率,在矩阵中不能向左走,路径长度为路径上权值为\(1\)的格子个数。

\(n\leq6,m\leq100。\)

思路

打死都不可能想到状态设计DP系列

参考了这篇博客的思路【51nod1683】最短路


概率乘了\(2^{n\times m}\)之后其实就是方案数,所以问题转化为了求满足题目条件的方案数

发现\(n\)很小,最大只有\(6\),考虑状压,但是不能直接维护当前格子的最短路,因为在多条并列最短路时会重复计数

考虑现在的\(0/1\)矩阵的特殊性:因为不能向左走,所以对于同一列中相邻两个格子之间的最短路最多相差\(1\)。因此考虑维护一整列最短路的差分数组。

记\(zt\)为一个三进制状态,表示该行从第二行开始,每个格子与上面的格子的差

设\(f[i][j][zt]\)表示第\(i\)列,第一行的最短路为\(j\),第\(2\)行~第\(n\)行的最短路的三进制为\(zt\)的方案数

转移时需要枚举下一列的\(0/1\)状态,线性更新一遍状态就可以了

时间复杂度为\(O(nm2^n3^{n-1})\)

代码见51Nod 1683 最短路

洛谷 P3592 [POI2015]MYJ

题意

给定\(m\)个区间\([a_i,b_i]\)以及\(c_i\),对于一个含有\(n\)个元素的序列\(ans[]\),区间\(i\)对其的贡献为\(\min\{ans_i\}(i\in[a_i,b_i])<=c_i\ ?\ \min\{ans_i\}(i\in[a_i,b_i])\ :\ 0\),要求构造一个序列\(ans[]\),最大化区间的贡献之和。

\(n\leq50,m\leq4000\)

思路

离散化+区间\(\texttt{DP}\)

稍作分析半天就会发现:存在一组答案使得每个\(ans_i\)都是某个\(c_i\)。因为把某个答案替换成第一个大于等于它的\(c_i\)不会更劣,因此\(c_i\)的值并不影响做题,但是大小顺序是有用的所以我们将\(c_i\)离散化。

因为一个区间的代价之和只与最小值有关,而且数据范围的\(n\)也不大,所以考虑区间\(\texttt{DP}\):

设\(f[l][r][k]\)表示区间\([l,r]\)内\(ans[]\)的最小值等于\(k\)的最大收益,\(g[p][j]\)为当前区间穿过\(p\),且\(c\geq j\)的区间数量

枚举最小的位置\(p\),那么包含\(p\)的区间的答案全都是\(k\),之后转移

\[f[l][r][k]=\max(\max(f[l][p - 1][k] + f[p + 1][r][k]+g[p][k]*k,p\in[l,r]),f[l][r][k+1])
\]

\(\texttt{DP}\)时顺便记录记录决策点,然后\(dfs\)输出

时间复杂度\(O(n^3m)\)

代码见洛谷 P3592 [POI2015]MYJ

洛谷 P4042 [AHOI2014/JSOI2014]骑士游戏

题意

有\(n\)个怪物,可以消耗\(k\)的代价消灭一个怪物或者消耗\(s\)的代价将它变成另外一个或多个新的怪物,求消灭怪物$的最小代价

思路

\(DP\)+最短路

看起来像是个\(\texttt{DP}\),认真思考一会儿也不难想到可以设计如下状态

设\(f[i]\)为消灭\(i\)所需的最小代价,那么有

\[f[i]=\min(f[i], s[i]+\sum\limits_{to_i} f[to_i])
\]

其中\(to\)表示\(i\)点的后继

因为\(f\)的转移之间相互干涉,所以用最短路处理

先建双向边,方便之后转移,然后用\(\texttt{SPFA}\)(它死了求"多源"最短路就好了

因为不知道一开始应该打哪个怪物,所以干脆全都入队、全部更新就好了

\(ps:\)两年\(\text{OI}\)一场空,不开\(long\ long\)见祖宗

代码见洛谷 P4042 [AHOI2014/JSOI2014]骑士游戏

DP没入门就入土的更多相关文章

  1. 【DP入门到入土】

    DP例题较多,可以根据自己需求食用~ update:下翻有状压DP入门讲解,也只有讲解了(逃~ DP的实质,就是状态的枚举. 一般用DP解决的问题,都是求计数或最优问题,所以这类问题,我们也可以用搜索 ...

  2. 树形动态规划(树形DP)入门问题—初探 & 训练

    树形DP入门 poj 2342 Anniversary party   先来个题入门一下~ 题意: 某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上 ...

  3. RocketMQ入门到入土(二)事务消息&顺序消息

    接上一篇:RocketMQ入门到入土(一)新手也能看懂的原理和实战! 一.事务消息的由来 1.案例 引用官方的购物案例: 小明购买一个100元的东西,账户扣款100元的同时需要保证在下游的积分系统给小 ...

  4. Hexo结合Stun静态博客搭建从入门到入土

    摘要 安装npm,安装hexo相关依赖,安装主题stun 修改hexo配置,修改stun配置,部署到github,gitee实现静态访问 给博客加上全局搜索,访问量统计 hexo博客编写模板 tips ...

  5. QT从入门到入土(一)——Qt5.14.2安装教程和VS2019环境配置

    引言 24岁的某天,承载着周围人的关心,一路南下.天晴心静,听着斑马,不免对未来有些彷徨.但是呢,人生总要走陌生的路,看陌生的风景,所幸可以听着不变的歌,关心自己的人就那么多.就像是对庸常生活的一次越 ...

  6. QT从入门到入土(二)——对象模型(对象树)和窗口坐标体系

    摘要 我们使用的标准 C++,其设计的对象模型虽然已经提供了非常高效的 RTTI 支持,但是在某些方面还是不够灵活.比如在 GUI 编程方面,既需要高效的运行效率也需要强大的灵活性,诸如删除某窗口时可 ...

  7. QT从入门到入土(三)——信号和槽机制

    摘要 信号槽是 Qt 框架引以为豪的机制之一.所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号 (signal).这种发出是没有目的的,类似广播 ...

  8. QT从入门到入土(四)——多线程(QtConcurrent::run())

    引言 在前面对Qt多线程(QThread)做了详细的分析:QT从入门到入土(四)--多线程(QThread) - 唯有自己强大 - 博客园 (cnblogs.com) 但是最近在做项目时候,要将一个函 ...

  9. [hdu 2089] 不要62 数位dp|dfs 入门

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意:求[n, m]区间内不含4和62的数字个数. 这题有两种思路,直接数位dp和dfs 数位d ...

随机推荐

  1. org.openqa.selenium.WebDriverException: It is impossible to create a new session because 'createSession' which takes HttpClient, InputStream and long was not found or it is not accessible 异常

    检查项目配置的jdk版本是否过低,修改一下配置就解决了.如果是jdk版本过低的就升级一下jdk.

  2. Android事件传递机制总结

    Android中控件的分类 Activity dispatchTouchEvent(MotionEvent e) onTouchEvent(MotionEvent e) ViewGroup(View) ...

  3. 01.Wireshark入门

    Wireshark官网下载地址: https://www.wireshark.org/#download

  4. Python--编码转换

    # -*- coding:gbk -*- # 即使设置文件编码为gbk,下方定义的字符串s1依旧为unicode # 获取默认编码格式 import sys print(sys.getdefaulte ...

  5. grafana 如何对数据进行切分

    也就是如何增加筛选,根据想要的条件筛选不同的内容,数据源是prometheus 效果 设置variable 正则表达式 匹配url中IP和端口 切片进阶 根据前一个切片 再过滤 含义说明 instan ...

  6. Ubuntu18.04 安装QQ、Tim、微信与win无差异

    一.安装deepin-wine环境: 桌面下打开终端,依次输入以下命令 git clone https://gitee.com/wszqkzqk/deepin-wine-for-ubuntu.git ...

  7. Python:三元表达式、列表推导式和生成器表达式

    三元表达式 语法格式 如下: 为真时的结果 if 判断条件 else 为假时的结果 例子 name = input('姓名>>: ') res = '请进' if name == '张三' ...

  8. 消息队列——Kafka基本使用及原理分析

    文章目录 一.什么是Kafka 二.Kafka的基本使用 1. 单机环境搭建及命令行的基本使用 2. 集群搭建 3. Java API的基本使用 三.Kafka原理浅析 1. topic和partit ...

  9. 使用Docker构建企业Jenkins CI平台

    在如今的互联网时代,随着软件开发复杂度的不断提高,软件开发和发布管理也越来越重要.目前已经形成一套标准的流程,最重要的组成部分就是持续集成(Continuous Integration,CI)及持续部 ...

  10. Python中用OpenPyXL处理Excel表格 - 单元格格式设置

    官方文档: http://openpyxl.readthedocs.io/en/default/ OpenPyXL库 --单元格样式设置 单元格样式的控制,依赖openpyxl.style包,其中定义 ...