DAGDP
食物链
简单的拓扑DP,转移方程通式 (f[v]+=f[u],rd[v]--)
犯错
for (int i=head[u];i;i=e[i].nxt)
{
int v=e[i].v;
f[v]+=f[u];
rd[v]--;
if (!rd[v]) q.push(v);
}
/*6,v写成i*/
for (int i=1;i<=n;i++)
if (!rd[i])
{
if (cd[i]) f[i]=1;
q.push(i);
}
/*特殊情况的处理,入队的对象*/
区间DP
P3205 [HNOI2010]合唱队
这是一种区间DP的典型模板,左右操作,求方案数
对于这类问题,可以分别表示左右两种操作
(f[i][j]) 表示在区间 ([i,j],i) 从左边插入
(g[i][j]) 表示在区间 ([i,j],j) 从右边插入
两个dp数组自然拥有独特的两个阶段
- 对于 (f): 相对于上一区间,要么是从 (i+1) 比较,再加入,或者上一次加进去的是 (j) ,则阶段为(f[i+1][j],g[i+1][j]),
注意这是上一阶段,换句话说就是该阶段的 (i)是被加入的,也就是上一阶段是不存在 (g[i][j])这中转移状态 - 对于 (g): 同理可耻,要么是上一次加入的是 (i),也就是加到左边,即 (f[i][j-1]),要么就是上一次加进去的是 (j-1) ,即 (g[i][j-1]);
注意上一阶段,不存在 (j) 的情况
错误 转移方程式抄错
for (int len=2;len<=n;len++)
for (int i=1;i+len-1<=n;i++)
{
int j=i+len-1;
f[i][j]=(f[i+1][j]*(a[i+1]>a[i])+g[i+1][j]*(a[i]<a[j]))%mod;
g[i][j]=(f[i][j-1]*(a[j]>a[i])+g[i][j-1]*(a[j]>a[j-1]))%mod;
}
/*6,抄错,炒成:g[i][j]=(g[i][j-1]*(a[j]>a[i])+g[i][j-1]*(a[j]>a[j-1])%mod/
总结 此类区间DP,转移的方向明确,要么上一阶段的左边要么右边,不需要区间枚举
Code
序列DP
粉刷匠
序列DP
对于每一行 (f[i][j]=max(f[k][j-1]+max(蓝 红,[k,i]))
对于每一行 (dp[i][j]),(i)表示行号,
(dp[i][j]=max(dp[i][j-k]+f[m][k]);)
答案 (dp[n][T]);
注意 处理前缀和优化时出现了错误
for (int k=0;k<l;k++)
{
// int s1=a[i][l]-a[i][k];
// int s2=b[i][l]-b[i][k];
int js=sum[i][l]-sum[i][k];
f[l][r]=max(f[l][r],f[k][r-1]+max(js,l-js-k));
}
树形DP
小齐挖矿
对于一个子节点,距离最近的要么就是父亲,要么就是父亲去的仓库
女仆咖啡厅桌游吧
tmd 燃起来了! 有点饲喂量的树形DP
-
暴力做法 求每个点的 (LCA)直接询问,不过会超时
-
树形DP
首先 (LCA)的一种性质,如果以 (i) 为节点的子树具有相同的最近公公祖先 (i),换句话说,若果这个点是某两个点的LCA,那么他的父亲必然是公公祖先
就这一性质,我们假设 (u) 即节点是第 (k) 层节点的最近公共祖先,那么就看看他的儿子 (v)是不是 (k+1)的了,
但是要 (v)成为深度 (k+1) 的LCA,必须满足子树 (v) 的最大深度超过 (k+1),故我们需要预处理出每个节点的最大深度
还有一种情况,如果 (u) 的儿子有多个,假若存在两个以上的 (v_1,v_2..) 满足 (f(v)>=k+1) ((f[v])表示该点的最大深度),那么他们都不可以成为LCA
P4438 [HNOI/AHOI2018]道路
记忆化搜索,树形思想,公式迷惑
P2899 [USACO08JAN]Cell Phone Network G
水题
P2458 [SDOI2006]保安站岗
水题
换根DP
P3478 [POI2008]STA-Station
换根式子:(f[v]=-size[v]+f[u]+(n-size[v]))
用人话讲就是:根有 (u) 到 (v)时,子树 (u) 全体深度+1(不含子树(v)),子树 (v)全体深度-1
P2986 [USACO10MAR]Great Cow Gathering G
换根水题
(ans)记得开大点,否则60
转移式子:(dp[v]=dp[u]-size[v] imes e[i].w+(sum-size[v]) imes e[i].w)
背包DP
关于二进制神奇做法的背包,感觉是在每一位二进制上进行背包
两个转移点
- 同级转移,我们有
(f[i][j]=max{f[i][j-a[i]]+val[i]}) - 高位转低位我们有
(f[i][j]=max{f[i][j-k]+f[i-1][min(1000,(k<<1)|((w&(1<<(b-1)))!=0)]})
二进制拆分,注意数组越界(拆分写挂,变成负数)
[P1782](https://www.luogu.com.cn/problem/P1782)
典型的旅行商问题,多重背包里套完全背包,我用的是二进制拆分(真好用,虽然60,这里建议直接吸氧!
期望DP
P1654 OSU!
装压DP
讲真的,装压是我见过最优美的DP题目
(f[i][s]) 表示起点为 (i),完成状态为 (s) 的最小距离
转移有 (f[i][s]=min{f[j][s-(1<<(i-1)]+dis(i,j)})
优美之处在于:距离不是限制矩阵的大小,只是运算的工具,通过位运算进行判重 if(!(s&(1<<(i-1))
,转移也非常优美,更新新的起点,并在二进制状态下更新,beautiftying
[USACO12MAR]Cows in a Skyscraper G
这题让初次学习的我知道了初始化,通过判断该点是否在状态之中,可谓妙哉!if((j)&(1<<k))
(f[i][j]) 表示有i个层时,满状态下的最小体积书
最后用过倒叙判断是否为inf
即可
P3226 [HNOI2012]集合选数
一道构造好题!