![](https://img-blog.csdnimg.cn/20201014180756928.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
动态规划
run around
这个作者很懒,什么都没留下…
展开
-
树上背包问题
树上背包问题主要是处理当前节点要从其儿子节点转移过来,但是儿子节点的第二维度是变化的,需要取出其中一个值与其他儿子的值拼凑出一个想要的值。所以就有背包的意味在里面了。洛谷P3177给定一棵n个节点的树,要求将k个点染成黑色,其余的点为白色。贡献为任意两个颜色相同的点的距离。求一个染色方案使得贡献尽可能的大。分析:计算贡献一般就是考虑每条边对答案的贡献,那么dp[i][j]就可以表示以i为根的子树,其中已经染了j个节点为黑色的最大贡献。这样对于转移我们就只需要加上这条的贡献了。但是对于儿子的枚举,看起原创 2021-01-07 15:06:43 · 978 阅读 · 0 评论 -
动态dp
/*动态dp,支持修改操作的dp最大值最小值维护定义广义矩阵乘法c[i][j]=max(a[i][k]+b[k][j]) 加法对min与max有结合律 对于转移g[i]=max(g[i-1],f[i]),f[i]=max(f[i-1]+a[i],a[i])尝试构造矩阵,利用线段树来维护区间的广义矩阵乘法的值,这样就能算区间的dp值 */#include <iostream>#include <cstring>using namespace std;typed原创 2020-11-24 17:45:40 · 297 阅读 · 0 评论 -
斜率优化DP
/*斜率优化主要解决的是转移方程中存在一个同时与i和j有关的部分时的优化问题 dp[i] = min(dp[j]+a[i]*b[j]) 0<j<i;转移方程写为dp[j]=-a[i]*b[j]+dp[i]那么决策就变为了二维坐标的点集,最小化dp[i]就转化为了线性规划问题对于线性规划问题,考虑任意三个决策点,根据方程的不同来判断斜率应该如何单调而决策点就在a[i]的临界处,即某个顶点左侧线段的斜率和右侧线段的斜率与a[i]大小关系不同。当a[i]单调时,我们就可以利用单调队列来维原创 2020-11-15 21:24:36 · 210 阅读 · 0 评论 -
SOS dp
/*sosdp:枚举子集合进行的一些操作也称高维前缀和 复杂度:O(n*2^n)计算对于任意的i,f[i] = sum(a[j]),j为i的子集合 dp[i][j]表示对于i来说,仅考虑前j位可能不同的子集合.如果i的第j位为1,那么dp[i][j]=dp[i][j-1]+dp[i^(1<<j)][j-1]即子集合中,第j位为1和第j位为0的前j-1位相加否则dp[i][j]=dp[i][j-1],即第j位一定只能为0 */ #include <iostream>原创 2020-10-04 22:44:48 · 138 阅读 · 0 评论 -
最长上升公共子序列
int dp[1005];int a[1005],b[1005];/*dp[i][j]表示考虑a的前i个元素,b的前j个元素且以b[j]结尾的最长上升公共子序列长度当a[i]!=b[j]时 dp[i][j] = dp[i-1][j] 第i个元素没用,b[j]一定是与前面的某个元素(或者啥也没有)配对当a[i]==b[j]时 dp[i][j] = max{dp[i-1][k]+1} 第i个元素与第j个元素配对,去前面找小于b[j]的结尾连接上去 */ int LICS(int n)原创 2020-07-08 19:48:18 · 163 阅读 · 0 评论 -
多重背包问题
#include <iostream>#include <queue>using namespace std;struct node{ int id,val; node(int a = 0,int b = 0) { id = a; val = b; }}q[100005]; //单调队列int dp[100005];int w[100005],v[100005],c[100005]; void slove(){ int s,n; cin原创 2020-06-21 09:47:33 · 118 阅读 · 0 评论 -
状态压缩
题意:给一个字符串,你可以反转任意一个字串,只能反转一次,找到一个最长不同字母字串的长度;思路:由于字符种类一共只有20种,对于这种种类数20左右的,我们都可以尝试用状压把所有状态都表示出来。在本题中,我们可以用dp[i]来表示i二进制表示的集合S的最大有效子集长度。那么我们允许翻转一次,也就是把两个没有交集的集合合在一起,即dp[i]+dp[(i<<20)-1-i]。那么dp[...原创 2019-10-07 23:26:49 · 79 阅读 · 0 评论 -
树形dp换根
换根解决的是“不定根”的树形dp问题。该类题目的特点是:给定一个树形结构,需要以每个节点为根进行一系列统计。方法为两次扫描来求解:第一次扫描时,任选一个点为根,在“有根树”上执行一次树形dp,在回溯时,自底向上的状态转移。第二次扫描时,从第一次选的根出发,对整根树执行一个dfs,在每次递归前进行自顶向下的转移,计算出换根后的解。题目:有一个树形的水系,由 N-1 条河道和 N 个交叉点组...原创 2019-09-19 17:00:24 · 2101 阅读 · 0 评论 -
数位dp
当题目中限制数字某一些位之间的关系时,一般用到数位dp洛谷2657windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?数位dp,判断出转移方程,查询即可,注意前导0/*数位dpdp[i][j]:第i位为j,后面位为任意数字,满足题目要求的数的个数 如51743 位数...原创 2019-08-06 10:40:54 · 118 阅读 · 0 评论 -
状压dp
洛谷1433房间里放着n块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在(0,0)点处。/*状压dp:复杂度O(2^n*n^2)dp[i][j]:表示当前位置为j,已经走了i的二进制表示中为1的那些点,每一位代表1,2,3,4...n;刷表法为:dp[state][k] = min(dp[state][k],dp[i][j] + cost[j][k]);i保证第k位为...原创 2019-08-05 09:57:27 · 191 阅读 · 0 评论 -
最长上升子序列LIS(n^2算法及nlogn优化)
题目: 有一个长为n的数列,求出这个序列中最长上升子序列n^2算法首先我们定义dp[i]表示以a[i]为末尾的最长上升子序列的长度,这样我们就可以得到递推关系:对于在i以前的元素,只要满足a[j]<a[i],那么我们就可以尝试把a[i]放在j元素的后面得到一个新的子序列长度的值,即dp[i] = max(dp[i] , dp[j] + 1) (j<i && a[j]...原创 2019-06-18 16:38:52 · 287 阅读 · 0 评论