【每日一题】DP 1
前言
考了两道 DP 原题,全都暴毙。。。
决定每天刷一些 DP 题并记录下来,题解详细程度根据难度不等。
P3354 [IOI2005]Riv 河流
7.19 树形 DP
一个自然的想法是设
由于子树中运上来的木料不好计算,而祖先点是确定的,可以用栈顺便记录,加上
转移见代码
// f[u][i][j]: u的祖先中上一个建伐木场的是i,子树u中建j个的最小花费
// g: 辅助转移。转移时表示u建伐木场的最小花费(f为u不建的)
void dfs(int u) {
stk[++tp] = u; // 栈中为u的祖先
for(int v = head[u]; v; v = nxt[v]) {
dis[v] = dis[u]+w[v];
dfs(v);
For(i,1,tp) rFor(j,m,0) { // m为题目中的k
f[u][stk[i]][j] += f[v][stk[i]][0],
g[u][stk[i]][j] += f[v][u][0];
// 手动转移一次,否则For(l)取min时f[u][stk[i]][j]保存的还是前面几颗子树的值
For(l,1,j) // 树上背包
f[u][stk[i]][j] = min(f[u][stk[i]][j],f[u][stk[i]][j-l]+f[v][stk[i]][l]),
g[u][stk[i]][j] = min(g[u][stk[i]][j],g[u][stk[i]][j-l]+f[v][u][l]);
// u建伐木场则子树v只需运到u。注意此时的j中并不包括在u建的这一个
}
}
For(i,1,tp) { // 计算点u的花费
rFor(j,m,1)
f[u][stk[i]][j] = min(f[u][stk[i]][j]+val[u]*(dis[u]-dis[stk[i]]),g[u][stk[i]][j-1]);
f[u][stk[i]][0] += val[u]*(dis[u]-dis[stk[i]]);
}
--tp;
}
P3232 [HNOI2013]游走
7.20 期望 DP(做过)
考虑先算每个点的期望经过次数
高斯消元(注意特判
边
贪心地标号
P3287 [SCOI2014]方伯伯的玉米田
7.22 DS 优化 DP
首先每次操作的右端点一定是
设
二维 BIT(拔高后的高度,拔高次数)优化。时间复杂度
P1453 城市环路
基环树 DP 7.25
先找环,以环上相邻的两点
P6064 [USACO05JAN]Naptime G
环形 DP 7.26
发现破环成链不好处理,那就强制令
注意初值、转移时的
P1272 重建道路
树形 DP 7.31
设
P3177 [HAOI2015]树上染色
树形 DP 8.1(做过)
按定义不好算点对之间的距离,考虑每条边的贡献,即它在多少个点对的路径上,只要知道子树中黑点数即可。
具体做法:ziidan Judge_Cheung
P4766 [CERC2014]Outer space invaders
区间 DP 8.2
发现外星人出现的时间对彼此有影响,考虑以时间 DP。
每个外星人都要打死,那么对于每一段时间
观察这个方程,存活时间跨过
有点笛卡尔树 DP 的感觉。
P5299 [PKUWC2018]Slay the Spire*
期望 DP 8.3
发现
首先考虑如果抽出的
分开 DP 强化牌和伤害牌。设
组合数的意义是在前
计算答案,分抽的强化牌数量考虑。
若小于
若大于等于
注意边界。同样可以前缀和优化,时间复杂度
CF908G New Year and Original Order*
数位 DP 8.3(博客是 8.4 写的,假装它是新的一天吧)
设
有一个经典的优化方式:
考虑转换每个数位排序后的贡献,即把
const int N = 705, mod = 1e9+7;
int len,ans,d[N],f[10][N][N];
int dfs(int u,int pos,bool lim,int x) {
if( !pos ) return !x;
if( !lim && ~f[u][pos][x] ) return f[u][pos][x];
int res = 0;
for(int i = 0, up = lim?d[pos]:9; i <= up; ++i)
res = (res + dfs(u,pos-1,lim&&i==up,x-(i>=u))) %mod;
if( !lim ) f[u][pos][x] = res;
return res;
}
signed main() {
memset(f,0xff,sizeof f);
For(i,1,9) for(int j = 1, k = 1; j <= len; ++j, k = (k*10ll+1)%mod)
ans = (ans + (LL)dfs(i,len,1,j) * k) %mod;
}
AT2000 [AGC002F] Leftmost Ball*
计数类 DP 8.6
结论:合法序列的任意前缀中白球数
考虑直接 DP 最终的颜色状态。设
P3648 [APIO2014]序列分割
斜率优化 DP 8.6
结论:一个切割方案的得分与顺序无关。
证明:假设切成了
采用贡献延迟计算的思想,设
发现这是一个可以斜率优化的式子,由于
P3959 [NOIP2017 提高组] 宝藏
状压 DP 8.8
见【杂题】NOIp
P3943 星空
状压 DP 8.13
先进行异或差分,把区间修改转化成两点修改。
问题转化为有
发现
时间复杂度也许是
P1450 [HAOI2008]硬币购物
背包 8.17
一个显然的做法是每次跑多重背包,但显然过不去。发现每次仅有
假定只有一种物品,那么不合法的方案相当于体积为
P5664 [CSP-S2019] Emiya 家今天的饭
计数类 DP 8.20
简化题意:给定一个矩阵,每行选一个点(每个位置有
不考虑合法性的情况数为
事实上没必要知道
P1350 车的放置
计数类 DP 8.22
设
一个问题是直接算的话在高度突变的地方不好处理(只知道前面放了几行,但不知道是哪些行),倒着 DP 即可。
P5017 [NOIP2018 普及组] 摆渡车
线性 DP 8.25
多次 TP 警告
P2059 [JLOI2013]卡牌游戏
期望 DP 8.27
如果对 DP 有较深理解,这题就很简单,但我没有。。。
考虑 DP 的条件之一:子问题重叠性,而本题中
设