背包
有限背包(多重背包)
拆分方法:倍增拆分
(倍增拆分!=二进制拆分)
拿走01背包
前后做两次DP,相当于前后缀
F[I][J]表示前i个物品,取体积为j的最大价值
G[i][j]表示第i+1到第n个物品,取体积为j的最大价值
拿掉第p个物品时,枚举a(0~m),拿走第p个物品后,最大价值就是f[p-1][a]+g[p+1][m-a]的最大值。
DP题很少删东西,都是加东西,所以把删转化为加
题目:https://darkbzoj.tk/problem/3163
边表
Struct edge{
int e, next;
}ed[maxn];
Int first[maxn];
Void ins(int s, int e)
{
En++;
Ed[en].next = first[s];
First[s]=en;
Ed[en].e=e;
}
树形DP
状态设计
F[i]表示以i为根的子树(必有这一维)
初始化
对叶节点做初始化
转移
把儿子合起来转移给父亲
最大独立集
没有上司的舞会 战略游戏
聚合
需要另外一个DP来聚合
依赖背包问题(树形背包)
基于连通性的状态压缩的动态规划——Cdq
题目
背包*3
独立集
树的直径
依赖背包问题
4516
送分
特殊类型DP
矩阵快速幂DP
思维难度DP
数位DP
一般框架:l~r之间满足条件的数的个数
统一状态设计
已知l,r,求l,r之间有几个数
转化为:
已知x求0<=y<=x中y的个数
状态
x=xk x(k-1) x(k-2)....x3 x2 x1
x有k位
y=yk.......
(y的位数未知)
F[i][j]表示方案数(个数)
i表示从高到低填到第i位, j=0/1表示当前我已经填的这些位是小于x还是等于x
一位一位转移
初始化
F[k+1][1]=1
转移
直接枚举第i-1位填啥
For(j = 0 to x_(i-1)) //对于f[i][1],y和x的前i位都相等,为了保证y<=x,y的第i-1位必须小于等于x的i-1位
F[i-1][x_(i-1)==1] += f[i][1]
答案
F[1][0]+f[1][1]
1.前缀和转化
2.状态设计有的i(位数),j(0/1)
(除非很特殊,告诉y有k位数(那就第1位填0,后面随便填。或第一位填1,)??
3.初始化
4.转移
练习
小凯的数字
代码
int solve(int x)
{
Memset(f,0,sizeof(f));
Int k=0;
While(x)
{
Y[++k] = x%10;
X = x/10;
}
F[k+1][1]=1;
For(int i=k+1;i>=2;i--) //已将填好i, 要填i-1
For(int j=0;j<=1;j++)
For(int r=0;r <=9;r++)
{
if(j == 1 && r >y[i-1] continue;
F[i-1][j &&(r==y[i-1])] += f[i][j]; //当j是1时,表示前i位都是相等的;当r=y[i-1]时,第i-1位也是相等的
}
Return f[1][0] +f[1][1];
}
Int l, r;
Ans=solve(r) – solve(l)
数位之和
F[i][j]表示个数
G[i][j]表示数位之和
r表示第i-1位填的数
对于第i-1位,g[i-1][j] += g[i][j] + k*f[i][j]
代码
int solve(int x)
{
Memset(f,0,sizeof(f));
Int k=0;
While(x)
{
Y[++k] = x%10;
X = x/10;
}
F[k+1][1]=1;
For(int i=k+1;i>=2;i--) //已将填好i, 要填i-1
For(int j=0;j<=1;j++)
For(int r=0;r <=9;r++)
{
if(j == 1 && r >y[i-1] continue;
g[i-1][j &&(r==y[i-1])] += g[i][j] + r*f[i][j]; //当j是1时,表示前i位都是相等的;当r=y[i-1]时,第i-1位也是相等的
}
Return f[1][0] +f[1][1];
}
Int l, r;
Ans=solve(r) – solve(l)
数位差大于2————多加一维
F[i][j][k] k表示第i位填的啥
练习
SCOI2009 BZOJ2006 P2657 windy
数位回文
DP一半
注意前面回文到后面要满足不大于x(唯一造成这个不合法问题)
状态
F[i][j][k] j=0/1,表示前i位的大小关系 k=0/1/2 表示后i位的大小关系
练习
SCOI2012 镜像数
数位乘积为k
如果某位填了0,k=0
DP1 k!=0
这个k含的质因子只有2,3,5,7,不然大于9没法用一位表示
质因数分解,如果有两位以上质因数,无解
F[i][j][a][b][c][d] [a][b][c][d]表示k,k=2^a +3^b + 5 ^c +7 ^ d
DP2 k==0
??????????
没法前缀和的时候
取MAX
状态
F[i][j][k][p]
I第几位,j=0/1 表示x 小于 r 或 x 等于 r, k = 0/1 表示x 大于l 或 x = l
P表示第i位填的是啥