dp
Glory_g
明日之我胸中有沟壑,立马振山河
展开
-
Codeforces 834D The Bakery【Dp+线段树】
题意 : 给你n个数让你划分成k个部分,每个部分对答案的贡献为这个部分不同数字的个数。问你答案最大为多少?题解 : 拿过这道题目我们不难想到动态规划做法,用dp (i,j) 表示前i个分成j部分最大答案是多少。则dp的状态转移方程为dp (i,j) = max (dp(x,j - 1) + diff (x + 1,i)); 但是这个状态转移方程的时间复杂度是 n^3 * k的显然是不可原创 2017-08-23 11:54:29 · 305 阅读 · 0 评论 -
POJ 1192 最优连通子集 (树形dp)
题解 : 对于这种 在 DAG 上求最大值的题目,很多情况下都是利用树形dp 去做这种题,这个也不例外dp (i,j) (j 只取 0、1) 表示第 i 个节点选择还是没选择的最大权值 dp (i,1) = c[i] + dp (son,1); (因为要求连通所以 不能选择 dp (son,0)); dp (i,0) = max (dp(son,1),dp(son,0)) 就是从儿子中找一个最大原创 2017-10-08 16:43:49 · 264 阅读 · 0 评论 -
HDU 1081 求最大子矩形 dp
这个题有树状数组的办法,这里我给出一种dp的办法,首先如果这个题目是一维的,那么应该都会做,要是多维的呢 ? 首先我们看一下一维的情况 比如 1 2 3 4 ans = 10,如果是二维的话我们就可以将第二维度压到第一维度, 3 4 5 6 加起来之后就是 4 5 6 7 ans = 22 以此类推就可以了。 取连续的子矩形才可以这么做的。#include <iostream>#include <原创 2017-10-08 20:26:46 · 386 阅读 · 0 评论 -
HDU 1114 完全背包dp
题解 : 这个题目就是完全背包,然后稍微推导一下就好了 dp (i,j) 表示的是前i个体积恰好为j是所能得到的最小价值 进行dp 转移就好了 #include <iostream>#include <cstring>#include <algorithm>#include <cstdio>using namespace std;const int maxn = 10005;const原创 2017-10-08 20:58:24 · 251 阅读 · 1 评论 -
Codeforces 453B B. Little Pony and Harmony Chest(dp+数论)
题解 : 首先发现这个题目中的 b 数组中每一个元素都不会超过 58 为什么呢 ? 自己想去 …. 然后我们发现,两个数互质就是没有相同的素因子,然后 1 -57 只有 18 个素数,先将这 18 个数打进一个表然后,用 state[i] 存下每个数包含的所有的素因子。 剩下的就是转移了 dp[i][j] 表示前 i 个 用了 j 这些素数 (j 是一个二维的压缩状态)。 dp[i原创 2017-10-19 15:35:05 · 415 阅读 · 1 评论 -
codeforces 486D D. Valid Sets(树形dp)
题解 : 由于这个题目说了是最大值和最小值的差,注意到数据范围,我们就可以枚举每一个值作为最大值然后去找联通块 就可以了 注意在这样做的时候有一个小问题就是出现与最大值相等的一个值的时候怎么办,我们可以规定好他们的顺序,每次选择下标大的或者下标小的那个都可以,这仅仅是为了避免重复。 dp (i) *= (dp (son) + 1) son 取遍 i 的所有儿子节点 #include <iost原创 2017-10-10 20:56:05 · 224 阅读 · 0 评论 -
codeforces 571B - Minimization (dp)
题意很好理解 题解 : 首先我们观察到几个事实就是说 : 1. 这 n 个数可以分成 k 段 并且这 k 段互不影响 2. 每个段内的数都是连续的数,因为只有这样,才能保证这个问题的最小性 3. 如果这 n 个数排序后每连续的两个作差取绝对值再求和答案是固定的也就是 max (a[i]) - min (a[i]) 。 4. 如果第三个是确定的并且可以保证每个段内的数都是连续的数,那我们所关原创 2017-10-11 20:17:46 · 458 阅读 · 0 评论 -
codeforces 583B B. Once Again...(LIS)
题解 : 我们要注意到一个东西就是说一个序列复制 n 遍一定到 lis 最后一个要么是最大的元素,要么是这个序列中重复最多的元素,这样的话,我们对于 t < n 的情况直接暴力求 lis 就可以,对于 t > n 的情况,我们先复制n遍,再把剩下的出现最多的元素加入到这个序列中去就可以了.#include <iostream>#include <algorithm>#include <cstri原创 2017-10-11 21:44:41 · 234 阅读 · 0 评论 -
codeforces 245H 区间dp
题解 : dp[i][j] 表示 第 i 到 j 有多少个回文串,match[i][j] 表示第 i 个 到 第 j 个能不能组成回文串转移就是 dp[i][j] = dp[i + 1][j] + dp[i][j-1] - dp[i][j]; if (s[i] == s[j] && match[i+ 1][j-1]) dp[i][j] ++;#include <iostream>#includ原创 2017-10-11 22:18:00 · 166 阅读 · 0 评论 -
CodeForces 158E Phone Talks dp
题解 : dp[i][j] 表示前 i 个选 j 个的最小需要的时间, 转移就是 dp[i][j] = min (dp[i - 1][j - 1],max(dp[i - 1][j] + a[i].d,a[i].t + a[i].d - 1)); 剩下的暴力每一个数,看它和它前面的时间差有多少就可以了。#include <iostream>#include <cstring>#include原创 2017-10-12 00:11:02 · 159 阅读 · 0 评论 -
codeforces 358D D. Dima and Hares(dp)
这个题目的关键之处在于你可以发现后面的选不选会影响前面的。所以我们要想办法把这一点去掉。 dp[i][0] 表示先选 i - 1 再选 i 前 i - 1个能获得的最大价值 dp[i][1] 表示先选 i 再选 i - 1 前 i -1 个能获得的最大价值 dp[i][0] = max (dp[i - 1][0] + b[i - 1] , dp[i - 1][1] + a[i - 1]);原创 2017-10-15 20:41:44 · 260 阅读 · 0 评论 -
codeforces 366C C. Dima and Salad(dp)
这个题 想法还是不错的 首先我们要求 sum (a[i]) 的最大值. 我们发现,每一个a[i] ,b[i] 的范围都很小 ,这里面一定有阴谋 hhh 这样的话我们可以用一个数组 c[i] 记录每一个 a[i] - k * b[i] ; 当作每一个物品的体积, 然后因为每个物品只能被选一个,我们怎么控制呢 ?c[i] >= 0 的我们算一次 c[i] < 0 的我们算一次,对于这两种情况这样原创 2017-10-15 21:04:10 · 272 阅读 · 0 评论 -
HDU 1080 Dp
题解 : 这个题一看就可以想到区间 dp 吧 一种还算是基本的模型dp (i,j) 表示第一个串匹配到第 i 个 第二个串匹配到 第 j 个的最大相似度 (记住一定是 匹配到 就是说以 i , j 为结尾) 的串 这样的话 根据所有可能的决策 不难想出状态转移的方程就是 dp (i,j) = max (dp (i - 1,j) + 用第二个串的j字符去匹配空格,dp (i,j - 1) + 用第一原创 2017-10-08 15:36:44 · 262 阅读 · 1 评论 -
HDU 1074 状态压缩dp
题意 :就是说有n门课程作业,每一门课程作业都有一个截止时间和完成作业所需要的时间,超出截止时间再交作业会被扣分,问你最少扣多少分。题解 :首先我们发现,作业的数目最大只有15,如果纯暴力的话,需要 15 ! 显然 时间复杂度不可以接受,这个时候就要想能不能状态压缩一下,把15!降到 2^15 * 15 这种复杂度,这样的话就不难想到状态压缩dp了 (可以思考一下,其实状态压缩的好处就在于它仅仅用原创 2017-10-08 14:06:54 · 208 阅读 · 0 评论 -
Codeforces Round #424 (Div. 2) Problem D. Office Keys
题意 : 给你n个人,每个人有一个位置,给你k把钥匙,每个人拿到钥匙才能到办公室,每人一秒走一步么,问你所有人到办公室的最短时间。题解 : 不难发现,当每个人拿的钥匙的位置确定了以后时间也确定了,我们就可以看每个人拿哪个钥匙,并且可以发现坐标靠前的人一定拿靠前的钥匙,否则结果不会更优。这样我们就可以先排序再dp。 dp[i,j] 表示 前 i 个人 在前j 把钥匙中拿到了全部的钥匙,转移方程为原创 2017-08-19 23:38:24 · 191 阅读 · 0 评论 -
HDU 5900 QSC and Master Sheng Yang 网络赛
题解: 我们可以先通过dp判断哪些可以进行合并然后再通过一维dp 得到最大值#include #include #include #include #define ll long longusing namespace std;const int maxn = 505;ll d[maxn] = {0};bool dp[maxn][maxn] = {0};ll a[maxn] =原创 2017-09-05 21:00:33 · 151 阅读 · 0 评论 -
HDU 2196 Computer(求树上每个节点到其它点的最远距离 树dp)
题意:求树上每个节点到其他节点的最大距离。题解 : 用树dp 首先我们发现每个节点要么先向上走要么先向下走,并且只要向下走就会一直向下走直到走到叶子节点,如果向上走那么下一步即可以向上走也可以向下走。我们用f[i] 表示第一步向下走时 i 节点走到的最远距离 g[i] 表示第一步向上走走到的最远距离,不难得到一个状态转移方程 : f[i] = max (f[j] + cost[i][j]) 其原创 2017-08-28 10:50:40 · 979 阅读 · 0 评论 -
2012-2013 ACM-ICPC, Asia Tokyo Regional Contest Beautiful Spacing 二分 + dp + 双指针扫描
题意 : 给你一个含n个单词的文本,按照一些规则放入宽度为w的矩形中,怎样使最大的空格最小。题解 : 首先我们可以发现答案是满足二分性质的,如果少的空格可以那么多的也一定可以,这样的话我们就可以对答案进行二分,判断一个mid 是否可以成为答案。我们定义dp[i]表示第i个单词能不能当某一行的末尾,这样的话,我们可以定义dp[0] = 1 认为一开始的满足的 (这就是边界条件),dp[i] 肯定原创 2017-09-13 20:21:55 · 459 阅读 · 0 评论 -
Codeforces Round #433 D. Jury Meeting
题解 : 对于这个题目我们可以使用 dp 两个方向进行dp1[i] 表示当 i 时间是从 所有点出发到 0 点的最小花费 ,dp2[i] 表示 i 时间时从 0点到 所有点 的花费最小值 这样我们就可以dp了 然后就是如果不能到 所有点我们就不更新如果可以到所有点我们就进行更新dp的最小值 过程中保留一个 sum 记录最小花费即可。#include #include #include #i原创 2017-09-07 17:48:59 · 217 阅读 · 0 评论 -
洛谷 小a和uim之大逃离
题意 : 有一个n*m的巨幅矩阵,矩阵的每个格子上有一坨0~k不等量的魔液。怪物各给了小a和uim一个魔瓶,说道,你们可以从矩阵的任一个格子开始,每次向右或向下走一步,从任一个格子结束。开始时小a用魔瓶吸收地面上的魔液,下一步由uim吸收,如此交替下去,并且要求最后一步必须由uim吸收。魔瓶只有k的容量,也就是说,如果装了k+1那么魔瓶会被清空成零,如果装了k+2就只剩下1,依次类推。怪物还说道,原创 2017-09-09 20:33:46 · 255 阅读 · 0 评论 -
Codeforces 864E Fire (DP)
题解 :这个题不难想到动态规划,但是想到动态规划并不能解决这个问题, dp[i,j,k0 表示前 i 个选了 j 个 用了 k 时间 所拯救物品的最大值,这样的话我们 就可以dp了 但是这个题和0\1背包的不同之处在于这个题选择的先后次序影响了这个题的答案 什么叫先后次序影响答案呢 ? 对于 0 1 背包而言,先选 a 后选 b 和 先选 b 后选 a 没有什么区别,但是这个题就不一样了原创 2017-09-26 21:54:15 · 395 阅读 · 0 评论 -
HDU 1011 树形 dp
题解 : 题目提示的很明确了 已经 树形dp 然后转移dp (i,j) 表示现在在节点 i 还有 j 个士兵 能获得的最大概率dp (i,j) = max (dp[(i,j),dp (son,k) + dp (i,j - k));注意这个题目是从叶子节点向根的dp 所以我们必须先把叶子节点的求出来才可以求根节点的答案 从底向上 更新dp 值 就可以了#include <iostream>#incl原创 2017-10-07 17:19:47 · 273 阅读 · 0 评论 -
HDU 1024 DP
题意 : 这个题目就是问你你一串数字分成 m 段连续和 问你 最大的划分是怎样的 输出这个划分和。题解 : 如果不计时间复杂度 和 空间复杂度的话我们不难设计出一个动态规划的方程就是 dp (i,j,k) 表示前 i 个分成 j 段 k 取 0 / 1 表示第i个数选没选 那么转移的方程为 dp (i,j,0) = max (dp(i - 1,j,0),dp[i - 1原创 2017-10-07 20:20:54 · 194 阅读 · 0 评论 -
HDU 1059 DP (完全背包 && 多重背包)
题意 : 给你6堆钻石,每一堆钻石的价值为 i 每一堆钻石有 i 个 问你能不能平分题解 : 这种问题一般来说应该是dp… 当然这个也不例外。dp (i) 表示 能不能用这么多钻石表示出 i 这么多的价值 dp 的取值为 0 / 1 表示不可以和可以。这样的话我们就可以进行转移了如果dp (i) = 1 的时候我们才进行转移 通过这种状态转移到后面的所有可能状态 dp (i + k * j) = 1原创 2017-10-07 21:48:30 · 183 阅读 · 0 评论 -
HDU 1069 DP
题解:首先我们要发现,这个题每一种长方体其实最多也就使用一次,因为题目说下面的要严格大于上面的低和宽,这样的话我们就可以把一个长方体拆成三个,分别作低和宽,然后我们按照底面的大小之类的东西排个序 (注意这个地方必须排序,因为这里不同于背包,选了前面对后面没有影响这个题目是有影响的)所有两个的话你会怎么选 非常关键 然后就是dp了dp(i) 表示前 i 个并且选择第 i 个的最大高度dp(i) =原创 2017-10-08 13:11:14 · 136 阅读 · 0 评论 -
codeforces 337D D. Book of Evil (树形 dp)
题解 : 我们发现可能藏着魔鬼的点就是那些,到所有被感染的点的最大距离小于等于d的点,剩下的我们的目的就是求出每个点到所有感染点的最大距离,这就是一个类似于求,树上的任意一个点,到所有点的最大距离,就是一个简单的树形dp;#include <algorithm>#include <cstring>#include <cstdio>#include <vector>#include <iost原创 2017-10-17 09:30:28 · 271 阅读 · 0 评论