DP
月光下的魔术师
这个作者很懒,什么都没留下…
展开
-
旅行商TSP问题
旅行商问题(TSP问题):每个点经过有且仅有一次的最短回路解法:动态规划HDU5067:经典TSP问题#include <bits/stdc++.h>using namespace std;int const inf = 0x3f3f3f3f;typedef pair<int,int>pii;int const N = 12;int n,m,mp[N][N],dp[1<<N][N],cnt;pii a[N];int TSP(){ /原创 2020-05-18 10:10:18 · 358 阅读 · 0 评论 -
整数划分问题
将n划分成若干正整数之和的划分数 设表示表示i划分成不大于j的划分数。 若,则 若,根据有无j进行划分: 如果划分中含有j,则 如果划分中不含有j,则 所以 若,根据有无j进行划分: 如果划分中含有j,则 如果划分中不含有j,则 所以 将n划分成若干不同整数之和的划分数设为将i划分为不超过j的不同整数的划分数若,则 若,根据有无j进行划分: 如果划分中含有j,则其余划分最大只能为,则 如果划分中不含有j,则 所以 若,根据有无j进行划分:原创 2020-05-17 21:33:03 · 610 阅读 · 0 评论 -
lightoj1151 Snakes and Ladders:概率DP+高斯消元
lightoj1151题意:有100个格子,从1开始走,每次随机走1~6。有n个格子会单向传送到其他格子,tp[i]表示从i传送到tp[i]。 1和100不会有传送,一个格子也不会有两种传送。问走到100投色子的期望值,注意不能走到100以外。题解dp[i]表示从i到100的还需要的期望次数 如果有传送门,那么dp[i] = dp[v[i]] 如果没有传送门:dp[i] = ...原创 2019-05-08 08:53:45 · 143 阅读 · 0 评论 -
lightoj1274Beating the Dataset :概率DP
lightoj1274题意:题目看半天看不懂~。说白了,就是设yes为1,个数为n1;no为0,个数为n2,在最前面加上一个1,求相邻不同的期望。题解dp[i][j][k]表示在第i个位置,前面(包括自身)有j个1,第i个位置为k相邻不同的期望。那么可以有两个转移,下一个为0或者1. p1表示为1的概率,p2表示为0的概率。最后求得是dp[0][0][1]。滚动数组优化一下。...原创 2019-05-08 08:47:52 · 260 阅读 · 0 评论 -
light1287Where to Run:概率DP
lightoj1287题意:如果能通过下一个点走完所有的点,那么这个点就叫EJ。如果EJ个数为0,不行动。否则,可以选择往任意一个EJ走或者在原地停留5分钟。求警察抓到你的期望时间。题解状态压缩+概率DP。 假设在u点有k种选择,包括停留5分钟。那么那么状态转移方程为: 则。注意当往其它点走时,要保证能够走完所有的点。 dp[s][u]表示已经走完的状态为s,目前处于i点,走完所...原创 2019-05-08 08:32:11 · 90 阅读 · 0 评论 -
lightoj1342 Aladdin and the Magical Sticks:概率DP
lightoj1342题解可区分的棍子n1,平均重量为s1。不可区分的棍子n2,平均重量为s2。 dp[i][j]表示已经有i个可区分和j个不可区分的,还需要的重量的期望。我们最后求的是dp[i][j] sum = n1 + n2 - i,下一次只能挑不可区分的和还未选中的可区分。即使选中了j个不可区分,下一次还是会挑到。 dp[i][j] = (n1 - i) / sum * (s...原创 2019-05-08 08:17:47 · 204 阅读 · 0 评论 -
lightoj 1284 Lights inside 3D Grid:概率DP
lightoj1284题意:初始灯都暗,随机翻转(1,1,1)到(x,y,z)之间的灯k次,求最后亮着灯的数量的期望。题解我们可以求出每一次每个点被选中的概率,再求出这个点被点亮的概率。最后求和便是期望。 假设一维情况,区间为[0,x],则一个点k被选中的概率为。三维就是分别计算x,y,z的乘积。 求这个点被点亮的概率,就是被翻转奇数次并且选中它的概率。即……、 这个化简为代码...原创 2019-05-07 22:46:22 · 96 阅读 · 0 评论 -
lightoj A Dangerous Maze 概率DP
lightoj1027题解无记忆性。 其中a表示正确的门的个数,sum1表示平均时间。b表示错误门的个数,sum2表示平均时间。 E(x) = a / n * aver1+ b / n * (aver2 + E(x))。 解的:E(x) = (a * aver1+ b * aver2) / (n - b) = (sum1 + sum2) / a代码#include &l...原创 2019-05-07 22:31:12 · 115 阅读 · 0 评论 -
HDU2476:区间DP
HDU2476题解首先将空串刷成目标串的最小方案数。 对于abbaa,我们两次就可以搞定。aaaaa-->abbaa,一次性连续刷一段,再刷中间。从头开始一段段刷是最差的方法。 再从给定串刷到目标串的最优方案。代码#include <bits/stdc++.h>using namespace std;int const N = 100 + 10;char...原创 2019-04-12 09:27:14 · 105 阅读 · 0 评论 -
HDU4283:区间DP
HDU4283题意:第k出场的嘉宾会有(k-1)*d的不满意度。 所以为了让不满意度最小,改变出场顺序,让嘉宾进入黑屋子。 第一个进入的是最后一个出去(堆栈)。题解dp[i][j]表示第i到第j个嘉宾都出场了的最优情况。 只有前面的区间才会对后面的区间产生影响,影响为前面区间的人数 * 后面区间的屌丝值总和。所以要保证每个区间最优,再合并。 如果在区间[i,j],i是第k个出...原创 2019-04-12 09:19:37 · 193 阅读 · 0 评论 -
ZOJ3469:区间DP
ZOJ3469题解对位置进行排序(包括外卖小哥的),然后求愤怒值的前缀和。 dp[i][j][k]表示送完[i,j]的所有人的最优方案,k = 0表示在i,k = 1表示在j。 dp[i][j][0]可以由dp[i+1][j][0]和dp[i+1][j][1]转移而来 同理dp[i][j][1]由dp[i][j-1][0]和dp[i][j-1][1]转移。 最后答案为min(dp[...原创 2019-04-12 09:10:48 · 140 阅读 · 0 评论 -
CF149D:区间DP
CF149D题解首先明确括号的匹配是惟一的。所以用一个栈模拟,用数组match记录左括号对应的右括号的位置。 染色要求是:可以染红或蓝或者无色。 每一对括号有且仅有一个染色。 相邻不能染相同的颜色,但可以都不染色。dp[i][j][p][q]表示i染p,j染q的区间方案数。0表示不染色,1表示红色,2表示蓝色。 dfs区间一遍。dfs(l,r),如果l和r匹配上,那么dfs(l...原创 2019-04-12 08:49:03 · 248 阅读 · 0 评论 -
lighitoj1042:区间DP
lightoj1042题解dp[i][j]表示第i天到第j天穿的最少的衣服。初始化dp[i][i] = 1(一天必须穿一件),dp[i][j] = inf。 如果第i天和第j天穿的是一件衣服,那么dp[i][j] = dp[i][j-1]。 剩下的就是区间DP模板。代码#include <bits/stdc++.h>using namespace std;int...原创 2019-04-12 08:39:45 · 78 阅读 · 0 评论 -
最优三角剖分 ZOJ3537 && UVA1331
UVA1331题解dp[i][j]表示从区间[i,j]最大三角形的最小值,中间找一点k。 状态转移为:dp[i][j] = min(dp[i][j],max(getarea(p[i],p[j],p[k]),max(dp[i][k],dp[k][j]))); 边界条件dp[i][i+1] = 0,其余初始化inf 如果出现上面的情况ABD,就不能组成三角形,中间包含点C。我们判断S...原创 2019-04-12 08:32:39 · 135 阅读 · 0 评论 -
luogu1063:区间dp
luogu1063题解类似矩阵最优连乘。 因为是环,所以再复制一份加在数组后面。 dp[i][j]表示起始位置是i,末尾是j的最大值。因为长的区间取决于短的区间。所以区间的长度要从小到大枚举。然后再枚举区间的起始位置,这样子末尾就确定了。然后枚举中间位置分割。 第i个柱子由p1✖p2构成,我们统一a[i]表示第i个柱子的前一个数即p1。 状态转移:dp[i][j] = max(dp...原创 2019-04-10 23:19:17 · 112 阅读 · 0 评论 -
HDU5758:树形DP
HDU5758题意:求一棵树最少有几条链构成,求链的最短长度和。题解首先必须明确,最少的链一定是从叶子结点到叶子结点。 如果叶子结点有奇数个,偶数个配对,剩下的一个向外面的叶子配对。 如果叶子结点有偶数个,正好可以两两配对。但这并不是最优方案,比如u有偶数个儿子,儿子之间正好配对,但是u可能又作为一个叶子结点和其它结点配对。这样子会导致链数增多。所以可以增加长度来减小链数。即有两个...原创 2019-04-15 08:06:05 · 250 阅读 · 0 评论 -
POJ1947:树形DP
POJ1947题解总共有n个结点的树,最少删去几条边,变成含有m个结点的子树。 dp[i][j]表示以i为根,含j个结点的树,最少需要删去的边数。 状态转移: dp[u][i] = min(dp[u][i],dp[u][i-j] + dp[v][j] - 1); 表示v这个子节点必须接上,所以不能删去u--v这一条边,所以删去数减1.代码#include <iostr...原创 2019-04-14 22:45:55 · 153 阅读 · 0 评论 -
HDU2196:树形DP
HDU2196题解在一棵树上,求每个结点能到达的最远距离。 设结点到子树的最大距离为深度。那么结点能到达的最远距离可能为深度(1),也可能为经过先到父结点再到兄弟结点的子树(2),或者直接一直往上走到另一边(3)。 如果u的父节点到子树的最大距离经过u,那么u的最远距离为max(1,2,3)。 如果u的父节点到子树的最大距离不经过u,那么max(2,3)。 先自底向上dfs一...原创 2019-04-14 22:00:59 · 253 阅读 · 0 评论 -
HDU6446:树形DP
HDU6446题解任何一种排列在树上都可以实现。那么我么固定两个结点i和j,记dis(i,j)为i和j的最短距离。那么从i和j放置数,有2*(n-1)种情况。剩下的n-2个点有(n-2)!种情况。所以一共有2*(n-1)!种情况。所以枚举i和j,求sum(dis(i,j)) * 2 * (n-1)!的和。 sum(dis(i,j))可以树形DP解决,即求树上任意两点之间的距离和。找一个结...原创 2019-04-14 21:25:38 · 132 阅读 · 0 评论 -
POJ3659:最小支配集
POJ3659题意:最小点覆盖所有的点。题解首先要明确最小支配集和最小点覆盖的区别。 最小点覆盖是选取最少的点,使所有的边都与集合的点相连。最小点覆盖 = 二分图最大匹配 最小支配集是选取最少的点,使所有的点都与集合的点相连。如果是树的话,树形DP解决。 在discuss有一组数据可以说明问题,放在代码最下面,自己画图看看。dp[i][j]以i为根的最小覆盖。 dp[...原创 2019-04-14 21:09:28 · 399 阅读 · 0 评论 -
树形DP二次扫描:POJ3585 && CF219D
POJ3585题解选择一个点,使它到所有端点的流量和最大。 一棵树,我们可求每个结点到子树的端点的最大流量和。DFS一遍,自低先上。设g[u]表示到u结点到子树端点的最大流量和,那么g[u] += min(g[v],e.cap)。v为root的子节点,e.cap表示这一条边的容量。如果下一个结点使叶子结点,那么直接加上e.cap,即g[u] += e.cap。 然后再DFS一遍,求结点...原创 2019-04-14 20:38:19 · 113 阅读 · 0 评论 -
树形DP:k结点子树最大权值和
很基础的一类题目,要用到01背包问题的思想。ZOJ3201题解含有k个结点的权值和最大的子树。 dp[i][j]表示以i为根的,含有j个结点的最大权值 dp[i][j] = max(dp[i][j],dp[i][j-k] + dp[v][k])。v是i的子结点。类似于分组背包问题,每个结点算一个组,每个组又有很多种选择。代码#include <bits/stdc++....原创 2019-04-14 19:44:00 · 1430 阅读 · 0 评论 -
CF903F:二维状态压缩DP
CF903F题解'*'用1表示,'.'用0表示。总共4行,从左到右一列一列遍历,使每一列按顺序变成0。 每一列的状态为state |= 1<<(4 * j + i)。i表示横坐标,j表示纵坐标。比如第一列全部是1,那么状态为0000 0000 0000 1111。第一行全部是1,状态为0001 0001 0001 0001。 具体实现见代码(详细)。代码#inclu...原创 2019-04-07 10:27:23 · 228 阅读 · 0 评论 -
CF152E:状态压缩
CF152E题意:翻转'.'为'X',使所有的'X'都相连,并且使花费最少。题解ydp[x][y][z]表示点(x,y)分割状态z为两部分s1和s2,两部分都经过点(x,y),并且满足s1&s2 = 0,s1^s2 = z。也就是说s1和s2无交集,其并集为z。有k个点是必须要经过的,状态z表示经过哪几个点的状态。 状态转移1:dp[x]][y][z] =min(dp[x][...原创 2019-04-07 09:44:01 · 507 阅读 · 0 评论 -
CF302E:Remembering Strings 状态压缩DP
CF302E题意每一行为好记满足:在这一行至少有一个字母在这一列是只出现一次的。 修改每一个字母都要费用,求使每一行都好记的最小费用。题解使一行的字母好记,可以修改某一个字母,或者修改这一列的与这个字母相同的字母,并保留花费最大。 状态压缩枚举,dp[i]表示状态i的最小花费。i中1表示好记,0表示不好记。我们不用判断这一行是否已经是好记,直接暴力枚举。如果好记,根据上面的修改方...原创 2019-04-07 09:11:47 · 124 阅读 · 0 评论 -
POJ1185:状态压缩dp
POJ1185题意只有p才可以部署部队,攻击范围是四周两格。求最多能够部署的部队个数。题解dp[i][j][k]表示第i行的状态为j,上一行的状态为k的方案数。 从上到下枚举每一行,进行状态压缩。判断相连三个1的个数是否≤1。 实际上每一行满足条件的状态数很少,所以可以预处理,只有60种状态。 判断这一行与上一行和上上一行是否冲突。如果状态i和j满足i & j = 1,...原创 2019-04-06 23:04:49 · 139 阅读 · 0 评论 -
POJ3254:状态压缩DP
POJ3254题意选择1,使任意两个1不能相邻。求方案数题解dp[i][j]表示第i行第j种状态的方案数。初始化dp[0][0] = 1。 枚举每一行种的方案数,首先必须满足不能有相邻的1,并且种的位置都是1。 从上到下枚举。这一行的上一行不能有相邻的1。代码#include <iostream>#include <cstdio>#includ...原创 2019-04-06 21:51:53 · 90 阅读 · 0 评论 -
CF417D:状态压缩DP
CF417D题意一共需要解决m道问题。小伙伴至少需要y台监视器才答应写题目,每台b元。每个人又需要x元的费用。给出每个人可以解决的题目。最少需要多少花费能够解决所有问题。题解状态压缩DP。把每个人可以解决的题目给状态压缩一下。 按监视器数量对大家排序。枚举到第i个人,那么编号≤i的人都满足监视器的要求。监视器的费用可以单独考虑。不用dp。 dp[i]表示能够解决i道题目的最小花费...原创 2019-04-06 21:37:58 · 128 阅读 · 0 评论 -
hihocoder1328:BFS最短路+状态压缩DP
hihocoder1328题解:这一题还是挺不错的,不是常规的BFS求最短路,而要加上钥匙的状态压缩。共三个状态。因为k<=5,钥匙的状态进行状态压缩,用v[x][y][k]表示在坐标(x,y)身上钥匙状态为k的步数每次走到有钥匙的地方,那么更新钥匙状态;走到锁的地方,判断是否有开这把锁的钥匙。代码:#include <bits/stdc++.h>usin...原创 2019-02-12 16:03:23 · 195 阅读 · 0 评论 -
luogu1064:有依赖的01背包
luogu1064题解有依赖的背包关系,实际上很好理解。我们只要考虑主件。 有5总状态要考虑。不选主件 只选主件 选主件和附件1 选主件和附件2 选主件和附件1和附件2其它都和01背包一样,只不过现在是多件物品。比如dp[i-主件的容量-附件1的容量] + 主件的价值 + 附件1的价值。诸如此类。代码#include <bits/stdc++.h>usi...原创 2019-04-14 19:16:41 · 138 阅读 · 0 评论 -
数位DP模板题
HDU2089题解代码(无前导0)#include <bits/stdc++.h>using namespace std;typedef long long ll;int const N = 10;int n,m,dp[N][N],a[N];int dfs(int pos,int pre,int sta,int limit){ if(pos == 0) ret...原创 2020-04-17 23:09:18 · 91 阅读 · 0 评论 -
二维背包
POJ2576题解:限制为人数和体重。人数差距不能超过1,体重越近越好。dp[i][j][k]表示考虑第i个人,能否达到人数为j,体重为k的状态。跑二维01背包最后再枚举各个状态,优先考虑人数,其次考虑体重代码:#include <cstring>#include <algorithm>#include <cstdio>#include...原创 2019-02-25 10:09:27 · 106 阅读 · 0 评论 -
HDU5534:背包问题
HDU5534题意:每个结点都有一个度数,每个度数都对应一个值。为了构成一棵树,最大值为多少。题解:普通思路点的个数为无限多个,所以为完全背包问题。。 每个点都是一件物品,其体积为度数,价值为度数对应的值,背包容量为2*(n-1)。我们要找n个点,使总价值最大。所以题目有两个限制,价值和数量,这是一个二维背包问题。 dp[k][i][j]表示考虑到第k种点,总度数为i,且有j...原创 2019-02-28 11:39:48 · 117 阅读 · 0 评论 -
ZOJ3524:
ZOJ3524题目:收集物品,不超过背包的容量,使收集到的价值最多 并且在价值最多的前提下,消耗的能量最小。最后输出消耗最小的能量。 消耗的能量为dist * weight。 每条路只能经过一次,不能再返回。题解:两个dp,先dp价值,在价值相同的前提下,dp消耗的能量。 拓扑排序找从s出发的所有路。拓扑排序的特点是结点一层一层的找。所以这一层的结点同时把下一层要更新的结点给...原创 2019-02-28 11:29:48 · 260 阅读 · 0 评论 -
CF1106E:multiset+dp
CF1106E题解:这一题有点麻烦,第一次用multiset。发现了神奇的erase让我一直WA,至今还是不懂。谁能告诉我orz!!!我们用dp[i][j]表示i时刻到n时刻用了j次阻拦,抢的最少红包。所以我们最后求min(dp[0][01…m]),发现了神奇的min_elemen函数。 我们已知dp[n+1][01……m] = 0,所以从后往前推。 用pair记录红包的价值w和d...原创 2019-02-23 12:28:10 · 106 阅读 · 0 评论 -
UVA11400:简单dp
UVA11400题解:每次都不换或全部把电压小的用电压大的替换掉,因为不全部换掉就有两个电源。 把灯泡按电压从小到大排序。这样换的时候直接用后面的换前面的。 dp[i]表示用1到i中几种灯泡的最小费用。 dp[i] = min{dp[j]+t[i].c*(sum[i]-sum[j])+t[i].k},表示前j个用最优方案,从j+1到i灯都替换为i号灯。 最后答案为dp[n];代码...原创 2019-02-22 18:37:10 · 109 阅读 · 0 评论 -
最长公共子序列(LCS)
最长公共子序列(LCS) dp[i][j] = x表示第一个字符串前i个位置和第二个字符串前j个位置的最长公共子序列长度为x if(s1[i]==s2[j]) dp[i][j]= dp[i-1][j-1]+1; else dp[i][j] = max(dp[i-1][j],dp[i][j-1])POJ1458(裸题)代码:很好理解。因为字符串从0开始,所以我i和j都分别加1记录...原创 2019-02-22 17:20:59 · 105 阅读 · 0 评论 -
UVA116:多段图的最短路
UVA116题解:参考刘汝佳的代码。每次从最后一列开始往前推。dp[i][j]表示从(i,j)到最后一列的整数和最小值。因为每次只能直行,右上,右下。所以dp[i][j] = max(dp[i][j+1],dp[i+1][j+1],dp[i-1][j+1])。 但是事情没有这么简单因为第一行的上面是最后一行,最后一行的下面是第一行。所以这里我们再开一个数组row[3],记录3个行,所以d...原创 2019-02-22 17:15:18 · 134 阅读 · 0 评论 -
HDU3535:分组背包
HDU3535题解:分组背包问题好题目。定义dp[i][j]为考虑到第i组,背包容量为j时的最大价值 s == 0,至少选一个。那么dp[i]初始化为-inf。dp[i][k]要从dp[i][k-weight]+val和dp[i-1][k-weight]+val转移过来。所以 dp[i][k] = max(dp[i][k],max(dp[i][k-weight]+val,dp...原创 2019-02-25 12:39:27 · 265 阅读 · 1 评论 -
背包问题模板
01背包问题(给定某种物品)for(int i=n;i>=1;i--){ //dp[i][j]表示处于从第i个阶段到最后一个阶段的最大花费 for(int j=0;j<=m;j++){ //必须遍历所有的状态 if(j<=weight[i]) dp[i][j] = dp[i+1][j]; else dp[...原创 2019-02-25 15:55:28 · 134 阅读 · 0 评论