动态dp
Posted call-me-zhz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态dp相关的知识,希望对你有一定的参考价值。
以前学树型dp留下的题目,没有写,然后过了几个月后又回来写了这道题
战略游戏
这是一道典型的最小点覆盖的模板,蒟蒻采用的是树型dp的做法
设 \\(f[i][0/1]\\) 在以 \\(i\\) 为根的子树中,选或不选当前这个点所需要的最少的点
那么转移方程为:
\\(f[i][0]=\\sum_v\\in son[i] f[v][1]\\)
\\(f[i][1]=\\sum_v\\in son[i] min(f[v][0],f[v][1])+1\\)
图片解释:
然后我们从根节点开始,\\(dfs\\) 遍历每一个节点,然后在每次遍历完一个节点后进行一次树型 \\(dp\\) ,注意,这个过程是从叶子结点到根的。
\\(Code:\\)
#include <iostream>
#include <cstdio>
using namespace std;
struct Node
int t;
int next;
node[30011];
int n,tot;
int f[3011][2],head[3011];
void add(int x,int y)
node[++tot].t=y;
node[tot].next=head[x];
head[x]=tot;
return;
void dfs(int u,int fa)
f[u][1]=1; //f[u][1]要初始化为1,因为它要选上自己这个点
for(int i=head[u];i;i=node[i].next)
int v=node[i].t;
if(v!=fa)
dfs(v,u);
f[u][0]+=f[v][1]; //如上面的转移方程
f[u][1]+=min(f[v][1],f[v][0]);
int main()
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;++i)
int step;
scanf("%d",&step);
++step;
int k;
scanf("%d",&k);
for(int j=1;j<=k;++j)
int y;
scanf("%d",&y);
++y;
add(step,y);
add(y,step); //因为题目中的标号是0~n-1,我为了方便就将每个节点加了1
dfs(1,0);
printf("%d",min(f[1][0],f[1][1]));
return 0;
但是,如果我们加上一个修改操作,每一次都进行修改,然后询问 \\(dp\\)值,这应该怎么做呢?
这就需要用到我们的标题:动态\\(dp\\) 了。
动态dp
这道题目要求的是最大点权独立集权值,我们把上面的方程稍微改一下,注意,是独立集,不是覆盖集
\\(f[i][0]=\\sum_v\\in son[i] max(f[v][0],f[v][1])\\)
\\(f[i][1]=\\sum_v\\in son[i] f[v][0]+a[i]\\)
图片解释:
注:\\(a[i]\\) 表示节点 \\(i\\) 的权值
我们首先回想一下矩阵乘法的式子:
\\(C_i,j=\\sum_k=1^pA_i,k* B_k,j\\)
然后我们来脑补一下\\(floyd\\) 的转移方程:
\\(f_i,j=min_k=1^nf_i,k+f_k,j\\)
嗯,为什么看起来这么相似呢?
好像只是把\\(\\sum\\) 换成了\\(min\\) ,$* $ 改成了 \\(+\\) 啊,这样子的矩阵乘法是对的吗?
答案是 \\(YES\\)
这时候我们就可以想到一种方法,我们能不能把转移方程改写成这种新定义的矩阵乘法的形式,然后用线段树来维护一段区间的矩阵乘法的乘积,从而实现 \\(nlogn\\) 的时间复杂度呢?
答案是 \\(Right!\\)
但是,我们上面的转移方程不好直接写成矩阵乘法的形式,我们将它改变一下:
设 \\(g[i][0/1]\\) 表示不包含\\(i\\)处在的重链上的节点(包括 \\(i\\))
\\(g[i][0]=\\sum_v\\neq son[i] max(f[v][0],f[v][1])\\)
\\(g[i][1]=\\sum_v\\neq son[i] f[v][0]+a[i]\\)
那么原来的转移方程就可以改为:
\\(f[i][0]=g[x][0]+max(f[son[i][0],f[son[i]][1])\\)
\\(f[i][1]=g[x][1]+f[son[i][0]\\)
改写成矩阵乘法的形式就是:
以上是关于动态dp的主要内容,如果未能解决你的问题,请参考以下文章