![](https://img-blog.csdnimg.cn/20190927151043371.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
动态规划
动态规划
Alex Su (*^▽^*)
清华大学计算机系硕士在读 ACM-ICPC银牌 CCPC银牌 蓝桥杯国一 天梯赛国一 CSP全国前50
展开
-
洛谷 P1156 垃圾陷阱 (01背包拓展)(好题!!)
这真是一道好题目学到了很多一开始感觉吃或者不吃会有后效性然后看到洛谷的题解,直接把这个有后效性的部分当作dp的维度和值因为这个垃圾可以堆或者不堆,所以这个很像01背包,但是加了非常多的限制条件,是一个升级版的01背包 记住思考01背包问题的时候,要思考i那一维度,最后再考虑要不要用滚动数组否则会增加思维难度这里有几个量,是高度,生命,时间因为时间是固定的,所以...原创 2018-08-29 08:20:44 · 194 阅读 · 0 评论 -
1113: [视频]树形动态规划(TreeDP)8:树(tree)(树形dp状态设计总结)
根据最近做的几道树形dp题总结一下规律。(从这篇往前到洛谷 P1352 )这几道题都是在一颗树上,然后要让整棵树的节点或边满足一种状态。然后点可以影响到相邻点的这种状态然后求最小次数那么要从两个维度来设计状态第一个维度(1)以i为根的树的所有节点都满足这种状态(2)以i为根的树的只有i不满足这种状态第二个维度(1)i这个点取(2)i这个点不取所以就会有四种状态,不过最近几...原创 2018-09-02 10:40:33 · 260 阅读 · 0 评论 -
caioj 1114 树形动态规划(TreeDP)3.0:多叉苹果树【scy改编ural1018二叉苹果树】
一波树上背包秒杀……#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#define REP(i, a, b) for(int i = (a); i < (b); i++)using namespace std;const int MAXN...原创 2018-09-02 11:05:07 · 248 阅读 · 0 评论 -
P1064 金明的预算方案 (依赖性背包问题)
这道题可以用分组背包来做。但是分组有两种方式一种是把主件,主件+附件1,主件+附件2分成一组组内只能选一个物品 一种是建一颗树,用树形dp的方式去做第二种更通用,就算物品的依赖关系是森林都可以做而第一种只限于这道题,因为只有一层关系,所以有特殊解目前只写了第一种,后面补第二种 #include<cstdio>#include<cstring>#...原创 2018-09-02 14:51:54 · 224 阅读 · 0 评论 -
洛谷 P1387 最大正方形
用f[i][j]表示以(i,j)为右下角的最长正方形的边长则 f[i][j] = min(f[i-1][j], min(f[i][j-1], f[i-1][j-1])) + 1;#include<cstdio>#include<algorithm>#define REP(i, a, b) for(int i = (a); i < (b); i++)#de...原创 2018-09-08 09:50:35 · 139 阅读 · 0 评论 -
洛谷 P1417 烹调方案 (01背包拓展)
一看到这道题就是01背包但是我注意到价值和当前的时间有关。没有想太多,直接写,0分然后发现输入方式不对……改了之后只有25分我知道wa是因为时间会影响价值,但不知道怎么做。后来看了题解,发现我对01背包理解不够透彻普通01背包做下来放入物品的顺序是1到n的因为这个时候顺序没有关系,所以可以直接做但是这道题后面放的物品价值小,所以价值有关系所以就要提前排好序。排...原创 2018-09-08 11:00:27 · 126 阅读 · 0 评论 -
洛谷 P1855 榨取kkksc03 (二维费用背包)
加多一维就行了#include<cstdio>#include<algorithm>#include<cstring>#define REP(i, a, b) for(int i = (a); i < (b); i++)#define _for(i, a, b) for(int i = (a); i <= (b); i++)using...原创 2018-09-08 11:08:23 · 146 阅读 · 0 评论 -
洛谷 P1736 创意吃鱼法
和最大正方形很像。记得对角线有两条还有2500不要开成3000,否则会mle#include<cstdio>#include<algorithm>#include<cstring>#define REP(i, a, b) for(int i = (a); i < (b); i++)#define _for(i, a, b) for(int...原创 2018-09-08 13:59:21 · 193 阅读 · 0 评论 -
洛谷 P1508 Likecloud-吃、吃、吃
这道题题好像写麻烦了因为道路从上到下和从下到上是一样的所以可以从上推到下,然后按照水牛开始位置输出结果。我是直接模拟水牛的移动,代码多了些。然后记住memset是必要的,不要省略,可能有负的情况#include<cstdio>#include<cstring>#include<algorithm>#define REP(i, a, b) fo...原创 2018-09-07 21:21:51 · 147 阅读 · 0 评论 -
洛谷 P1282 多米诺骨牌
这道题很有收获。我自己想的时候有想到这是一个背包,但是写的实现非常麻烦,还是错的。我想的是在背包的过程中尽量靠近0,但是这样显然有后效性而且我思考背包的方式不对。要考虑当前物品有哪几种可能,然后比如这道题就是交换或者不交换。先用二维的思考方式,滚动数组只是后面的优化。后来看了题解,很有收获 (1)如何防止下标为负数。可以设一个基准数base,然后每次涉及到重量的都加上b...原创 2018-09-07 20:48:28 · 134 阅读 · 0 评论 -
caioj 1079 动态规划入门(非常规DP3:钓鱼)(动规中的坑)
这道题写了我好久, 交上去90分,就是死活AC不了后来发现我写的程序有根本性的错误,90分只是数据弱#include<cstdio>#include<algorithm>#define REP(i, a, b) for(int i = (a); i < (b); i++)using namespace std;const int MAXN = 21...原创 2018-08-25 10:35:56 · 339 阅读 · 0 评论 -
洛谷P1108 低价购买 (最长下降子序列方案数)(int,long long等 范围)
这道题用n方的算法会很好做我一开始想的是nlogn的算法求方案数,然后没有什么想法(实际上也可以做,但是我太弱了)我们就可以根据转移方程来推方案数,只是把max改成加,很多动规题都是这样,比如背包的方案数。设f[i]为以i为结尾的方案数当 b[j] + 1 == b[i] 且 a[j] > a[i]时,f[i] 加上f[j]同时要去重,当b[i] == b[j] 且 a[i] ...原创 2018-08-29 18:56:00 · 220 阅读 · 0 评论 -
hdu 1712 (分组背包)
最近在做树形dp,遇到几道多叉树的问题都可以用树上背包的做法来做。还不是很懂,据说是分组背包,所以我就找了一道分组背包的题来打打基础摘自《背包九讲》 这里循环顺序要注意先枚举重量后枚举物品可以使得只取一个物品然后最外层就是组#include<cstdio>#include<algorithm>#include<cstring>...原创 2018-09-01 11:24:47 · 200 阅读 · 0 评论 -
洛谷 P1273 有线电视网 && caioj 1109 树形动态规划(TreeDP)4:比赛转播(树上分组背包总结)
从这篇博客往前到二叉苹果树都可以用分组背包做这依赖性的问题,都可以用于这道题类似的方法来做表示以i为根的树中取j个节点所能得的最大价值那么每一个子树可以看成一个组,每个组里面取一个节点,两个节点,三个节点就是三个不同的物品对于这道题,有我们来类比一下普通分组背包的转移方程这里的k表示第几组,而在树上就直接用i表示,因为i已经包含它的子树的信息了然后 相当于, 后面的...原创 2018-09-01 11:51:03 · 201 阅读 · 0 评论 -
caioj 1080 动态规划入门(非常规DP4:乘电梯)(dp数组更新其他量)
我一开始是这么想的注意这道题数组下标是从大到小推,不是一般的从小到大推f[i]表示从最高层h到第i层所花的最短时间,答案为f[1]那么显然f[i] = f[j] + wait(j) + (j - 1), j > i也就是说枚举从哪个楼层过来。取最优wait(j)表示从第j个楼层等待电梯的最短时间。这个算法应该是正确的,但是时间复杂度很大有n个电梯,h层的话枚举i和j要h *...原创 2018-08-25 15:06:21 · 250 阅读 · 0 评论 -
caioj 1081 动态规划入门(非常规DP5:观光游览)
这道题和前面的分组的题有点像就是枚举最后一组的长度。然后组数可以在第一层循环也可以在第二层循环我自己的话就统一一下在第一层循环吧然后这道题题意我一直没理解清楚,浪费了很多时间,写复杂了同时初始化的问题很重要。f[i][j]为前i格j个人分配的最大值f[0][0] = 0,其他为负无穷因为这道题很严格,有些状态是不存在的(比如前5格分配6个人),这个时候就要设负无穷表示不存在这...原创 2018-08-25 17:24:00 · 320 阅读 · 0 评论 -
洛谷 P1352 没有上司的舞会 (树上不相邻点权和最大)
一颗树,选取不相邻的点,求最大点权值因为当前结点选或不选后后效性,所以我们加一唯来取消后效性表示以i为根的树且i不选的最大价值表示以i为根的树且i选的最大价值显然有#include<cstdio>#include<vector>#include<algorithm>#define REP(i, a, b) for(int i ...原创 2018-09-01 14:23:18 · 176 阅读 · 0 评论 -
caioj 1111 树形动态规划(TreeDP)6: 皇宫看守 (状态设计)
这道题的难点在于状态怎么设计这道题要求全部都是安全的,所以我们做的时候自底向上每一个结点都要是安全的结合前一题当前结点选和不选,我们可以分出四种情况出来选 安全选 不安全不选 安全不选 不安全显然选 不安全是不可能的,那么就去掉所以我们就可以设计状态为表示i放人且安全表示i不放人且安全表示i不放人且不安全那么状态转移方程最关键的就是怎么保证回溯的时候都是安全的。我们只考虑以...原创 2018-09-01 16:27:42 · 291 阅读 · 0 评论 -
caioj 1112 树形动态规划(TreeDP)7:战略游戏
这道题和上一道题非常相似这道题是看边,上一道是看点。但是状态定义不同看边的话没有不放不安全这种状态因为当前结点的父亲无法让这颗子树没有看到的边看到所以这种状态不存在而上一道题存在不放不安全这种状态因为当前结点的父亲可以让这个不安全的结点变得安全边和点是两种不同的思考方式,得出得状态和方程也就不一样了还有这题不知道根。多叉树随便选个点做根,然后注意不要递归到父亲就...原创 2018-09-01 16:52:06 · 180 阅读 · 0 评论 -
洛谷 P1220 关路灯 (贪心+区间dp)
这一道题我一直在想时间该怎么算。看题解发现有个隐藏的贪心。路径一定是左右扩展的,左右端点最多加+1(我竟然没发现!!)这个性质非常重要!!因此这道题用区间dpf[i][j]表示关完i到j的路灯的消耗。那么因为要算走的路程,那么还有一维表示当前人在左端点还是右端点。然后每次的消耗为当前走这一段的时间乘上这个时候还亮着的路灯的总功率。然后这个起点的意义就在于在起点的消耗为0,其他都...原创 2018-09-11 17:20:05 · 112 阅读 · 0 评论 -
洛谷 P1541 乌龟棋 (四维费用背包)
一开始直接用01背包后来发现这个物品和位置有关。也就是价值不是固定的后来看了题解看了卡片最多就4所以这是一个四维费用的背包,每一维是卡片的数量价值就是当前的位置的价值。但是与常规的背包还是有点不同代码中没有枚举物品这一项实际上循环里面的四个卡片的判断语句就是枚举四个物品这里是先体积后物品,保证了这四个物品只选了一件分组背包中同一组内物品的循环顺序也是先提及后物品...原创 2018-09-08 14:37:51 · 167 阅读 · 0 评论 -
HDU3001 Traveling (状压dp+三进制+Tsp问题总结)
(1)这道题最多可以走两次,所以有0, 1, 2三种状态,所以我们要用三进制如果要用三进制,就要自己初始化两个数组, 一个是3的n次方,一个是三进制数的第几位的数字是什么void init(){ three[0] = 1; REP(i, 1, 11) three[i] = three[i-1] * 3; REP(i, 0, three[10]) { int t = i;...原创 2018-09-24 10:44:02 · 168 阅读 · 0 评论 -
poj 2288 Islands and Bridges (状压dp+Tsp问题)
这道题千辛万苦啊!这道题要涉及到当前点和前面两个点,那就设dp[state][i][j]为当前状态为state,当前点为i,前一个点为j这个状态表示和之前做炮兵那题很像,就是涉及到三个点时,就多设一维表示前一个点(炮兵那题把点换成行)这道题有很多细节需要注意(1)计算路径长度。这道题一开始怎么不重复又方便的计算长度难住了我。后来看到题解直接在初始化的时候算上路径,非常牛逼然...原创 2018-09-24 12:23:33 · 178 阅读 · 0 评论 -
zoj 3471 Most Powerful(状压dp+Tsp问题+连续性问题)
上来直接一波敲键盘,直接套Tsp问题的代码然后WA发现貌似这道题没有连续性。Tsp问题是一条路径,一个点到另一个点,多了一个限制,所以就需要加多一维而这道题没有限制,也就是说那一维不需要加,我加了还WA然后要搞清楚状态,在纸上可以写,写清楚了再敲代码这道题一开始都是存在,初始状态是0000……所以就用0表示存在,1表示不存在#include<cstdio>...原创 2018-09-24 14:54:28 · 117 阅读 · 0 评论 -
poj2411 Mondriaan's Dream (状压dp+多米诺骨牌问题)
这道题的解析这个博客写得很好https://blog.csdn.net/shiwei408/article/details/8821853大致意思就是我们可以只处理两行之间的关系,然后通过这两个关系推出所有行(有点像矩阵快速幂的思想)几个要注意的地方(1)第0行为全1(2)发现自己的思维习惯还是先行在状态,我自己写得时候老是写反。(3)path的个数可能有很多,不只是1&l...原创 2018-09-24 16:12:06 · 247 阅读 · 0 评论 -
poj 2663 Tri Tiling (状压dp+多米诺骨牌问题+滚动数组反思)
本来直接一波状压dpAC的#include<cstdio>#include<cstring>#include<algorithm>#define REP(i, a, b) for(int i = (a); i < (b); i++)#define _for(i, a, b) for(int i = (a); i <= (b); i++)...原创 2018-09-24 16:43:34 · 231 阅读 · 0 评论 -
poj 3420 Quad Tiling (状压dp+多米诺骨牌问题+矩阵快速幂)
还有这种操作??????直接用pre到now转移的方式构造一个矩阵就好了。二进制长度为m,就构造一个长度为1 << m的矩阵最后输出ans[(1 << m) - 1][(1 << m) - 1]就好了牛逼!#include<cstdio>#include<cstring>#include<algorithm...原创 2018-09-24 17:02:59 · 268 阅读 · 0 评论 -
洛谷 P1169 [ZJOI2007]棋盘制作 (悬线法)
和玉蟾宫很像,条件改成不相等就行了。悬线法题目 洛谷 P1169 p4147 p2701 p1387 #include<cstdio>#include<algorithm>#define REP(i, a, b) for(int i = (a); i < (b); i++)#define _for(i, a, b) for(int i = (a)...原创 2018-09-14 19:39:36 · 131 阅读 · 0 评论 -
洛谷 P2577 [ZJOI2005]午餐
首先吃饭时间长的排在前面更优,所以先排个序然后问题就是怎么分配这一波人的问题刻画状态有人和时间,然后分两队所以用表示前i个人,第一队用j时间,第二队用k时间的最小吃饭时间那么因为这么开数组会炸,所以我们要降一维。前i个人的等待总时间是固定的,所以第二队的时间可以推出来那么接下来就是非常非常关键的状态转移方程了t是当前人的打饭时间,p是当前人的吃饭时间第一个方...原创 2018-09-14 22:38:43 · 162 阅读 · 0 评论 -
洛谷 P1070 道路游戏
设为第i秒获得的最大值表示从当前世界是j,从pos走k步到当前点i的最大价值注意这里的sum可以利用前面的值逐步累加。我开始做的时候没有想到这一点单独求,然后就超时了。同时要注意循环的循序问题。#include<cstdio>#include<cctype>#include<algorithm>#include<cstring>...原创 2018-09-15 11:13:06 · 201 阅读 · 0 评论 -
poj 3311 Hie with the Pie (状压dp) (Tsp问题)
这道题就是Tsp问题,稍微加了些改变注意以下问题(1)每个点可以经过多次,这里就可以用弗洛伊德初始化最短距离(2)在循环中集合可以用S表示更清晰一些(3)第一维为状态,第二维为在哪个点,不要写混。(4)在dp过程中0这个点是不用的,只用到1到n这个点而实际上dp过程中用的是0到n-1,所以就枚举1到n,然后涉及到集合的地方就写i-1其他地方如dp的第二维,距离这些都不变...原创 2018-09-23 23:26:21 · 94 阅读 · 0 评论 -
POJ 1185 炮兵阵地 (状压dp)(棋盘dp)
这题和poj 3254很像,但是更复杂了一些都属于棋盘里放东西,然后又各种各样的限制,然后求方案或者最大值(1)上一道题距离要大于1,这道题是大于2。所以判断的时候变成!(x & (x << 1) || (x & x << 2))然后关于有效状态数,可以自己输入最大的数据,例如这道题就是n=10,然后输出状态数,就可以得到等于60(2)...原创 2018-09-23 22:37:44 · 285 阅读 · 0 评论 -
洛谷 P1052 过河 (离散化+dp)
dp非常好想, f[i] = min(f[i-len] + stone[i]) s <= len <= t然后因为L非常大,所以我就不知道该怎么搞了我看到m只有100,而L有1e9,我就知道肯定要通过某种数学方法来离散化然而我并没有想出来这个数学方法看来题解,原来这个方法很简单,我怎么就没有想到因为最大走10步,所以把距离对1到10的最小公倍数是2520取模就好了。离散化...原创 2018-09-08 15:39:10 · 180 阅读 · 0 评论 -
洛谷 P1880 [NOI1995]石子合并
这道题是之前石子合并的加强板https://blog.csdn.net/qq_34416123/article/details/81913341不同在于是一个环处理方法就是把数组 乘以2,枚举起点转化成链。以后这种环的问题应该都可以这样来转化。数组空间不要忘了乘以2然后要注意区间从长度为2开始,初始化为最大或最小注意这里的得分是合并之后的得分,所以单独一堆是没有得分的。...原创 2018-09-05 18:47:19 · 105 阅读 · 0 评论 -
洛谷 P1026 统计单词个数 (分组+子串预处理)(分组型dp再次总结)
一看完这道题就知道是划分型dp有两个点要注意(1)怎么预处理子串。 表示以i为开头,结尾在j之前(含),有没有子串,有就1,没有就0(2)dp的过程这种分成k组最优的题目已经高度模板化了,我总结一下吧//f[i][j]表示把前j个数分成i组的最优价值 memset(f, 0xc0, sizeof(f)); //初始化 f[0][0] = 0; //不要...原创 2018-09-09 09:53:58 · 170 阅读 · 0 评论 -
洛谷 P1005 矩阵取数游戏 (区间dp+高精度)
这道题大部分时间都在弄高精度……还是先讲讲dp吧这道题是一个区间dp,不过我还是第一次遇到这种类型的区间dpf[i][j]表示取了数之后剩下i到j这个区间的最优值注意这里是取了i之前和j之后的,i到j的数并没有取。那么这个状态要不是取了第i-1个数转移而来,要不是取了第j+1个数转移而来。所以可以写出方程 f[i][j] = max(f[i-1][j] + a[i-1] * mi[m-...原创 2018-09-09 15:56:40 · 240 阅读 · 0 评论 -
洛谷 P2279 [HNOI2003]消防局的设立 (树形dp or 贪心)
一看到这道题就知道是树形dp之前做过类似的题,只不过保护的范围是1所以简单很多。这道题保护的范围是2,就复杂了很多。我就开始列状态,然后发现竟然有5种然后我就开始列方程。但是我考虑的时候是用一条链去思考的。显然应该要用深度为3的完全二叉树去思考。所以我写到一半发现自己的方程有问题。然后就干脆放弃了,因为思维量好大。然后去看题解。发现我完成了正解的三分之一。后面的方程写出之后...原创 2018-09-12 17:24:52 · 433 阅读 · 0 评论 -
洛谷 P1373 小a和uim之大逃离 (差值型dp总结)
这道题和多米诺骨牌那道题很像,都是涉及到差值的问题。这道题是二维的,同时要取模.这种题,因为当前的决策有后效性,会影响到差值,所以直接把差值作为维度,然后计算答案的时候把差值为0的加起来就行了。这里有两个人,所以可以多设一维第一人还是第二人,来回更新。然后取模的时候记得+k再模k#include<cstdio>#include<algorithm>#...原创 2018-09-10 18:22:21 · 93 阅读 · 0 评论 -
Vijos 1456 最小总代价 (状压dp)
看到这道题n只有16,就可以想到状压dp每个人只有经过或者没经过,那就用1表示经过,0表示没经过但是不是当前在谁那里,所以再加一维来记录所以f[state][i]表示在物品在i,当前的状态是state情况下的最小总代价有几个细节要注意 (1)刷表法。要提前初始化为-1,然后然后每个起点为0.。做的时候要判断当前状态存不存在。(2)之前状态存在,当前这个人不存在才可以去做...原创 2018-09-23 13:58:11 · 162 阅读 · 0 评论 -
poj 3254 Corn Fields (状压dp)(棋盘dp)
状压dp入门题因为当前行的状态只和上一行有关所以可以一行一行来做因为m <= 12所以可以用二进制来表示放了或者没有放0表示没放,1表示放f[i][state]表示第i行状态为state的方案数f[i][state] = sum(f[i-1][state'])枚举行,然后枚举这一行和上一行的状态最后把最后一行所有状态的和加起来就行了 状态是这么定义,但...原创 2018-09-23 17:20:28 · 90 阅读 · 0 评论