DP选做
DP选做
P4805 [CCC2016] 合并饭团 [区间DP] [单调性优化] [提高+/省选-]
和普通区间DP有一点点区别,就是多加了一个三个区间的合并
至于普通合并是
即左区间的右端点右移时右区间的左端点一定左移,区间相等后还要看中间区间能不能变成一个饭团
P2238 逛庙会 [普通DP] [状态压缩] [省选/NOI-]
考虑一开始想的是压上下左右四个状态,后面发现只有下和右状态有用
接下来发现做法假了,比如说从上往下转移时,转移到的格子的左边那个格子的状态不见了
后来发现需要记录4个格子
然后写了
check: (int i,int j,int k){ if(get(k,0) && (i == 0 || shop[i-1][j+1] == 0)) return 1; if(get(k,1) && shop[i][j+1] == 0)return 1; if(get(k,2) && shop[i+1][j] == 0)return 1; if(get(k,3) && (j == 0 || shop[i+1][j-1] == 0)) return 1; return 0; } main: for(int k = 0; k <= 15; ++k)dp[1][1][k] = 0; for(int i = 1; i <= H; ++i){ for(int j = 1; j <= W; ++j){ if(i == 1 && j == 1)continue; for(int k = 0; k < 16; ++k){ if(get(k,1) && get(k,2))continue;//下和右不可能都没与处理 if(check(i,j,k)) continue; int up,down,left,right,now; balabala...//上向下 for(int l = 0; l < 16; ++l){ if(get(k,0) == 0 && shop[i-1][j+1] != 0)break;//0号点一定没处理过 if(check(i,j-1,l))continue;//检查合法性 if(get(l,2) != get(k,3)) continue;//前面的二号点等于现在的三号点 (继承) if(get(k,1) + get(k,2) > 1)continue;//没处理的点的个数不能超过1个 left = 0,down = (get(k,2)^1) * shop[i+1][j],right = (get(k,1) ^ 1) * shop[i][j+1]; if((get(k,1) || get(k,2)) && get(l,0)) up = shop[i-1][j];//上面的点如果能不处理就不处理 else up = 0; now = get(l,1) * shop[i][j];//左面没处理当前点就处理 dp[i][j][k] = min(dp[i][j-1][l] + up + down + left + right + now,dp[i][j][k]); }//左向右 } } }
P2051 [AHOI2009] 中国象棋 [普通DP] [组合数学] [打表] [提高+/省选-]
法一:DP
状态设置:
一开始想到的是部分分十分的显然,就是一个状压DP,但是有没有一种可能,对于前
法二:打表
考虑把表打完好像交不了,那就打像三角形一样的一半即可,这里就不给出打的表了,有点长……
P3177 [HAOI2015] 树上染色 [树型DP] [上下界优化] [提高+/省选-]
计算每一条边的贡献,就是(下面的黑点数×上面的黑点数+下面的白点数×上面的白点数) ×边的边权
考虑需要进行上下界优化
void dfs(int u,int fa){ siz[u] = 1; for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].to,val = edge[i].val; if(v == fa) continue; dfs(v,u); siz[u] += siz[v]; for(int j = min(siz[u],m); j >= 0; --j) for(int k = max(0,j - (siz[u] - siz[v])); k <= min(siz[v],j); ++k){ if(dp[u][j-k] == -1) continue; ll tot = val * ((ll) k * (m - k) + ((ll)siz[v] - k) * (n - m - siz[v] + k)); dp[u][j] = max(dp[u][j],dp[u][j - k] + dp[v][k] + tot); } } }
本质上就是说对
[POI2017]Sabotaż [树状DP] [提高+/省选-]
solution 1:二分答案
考虑每次二分一个答案,然后进去去跑一遍看他能不能跑出
solution 2:树状DP
考虑设计状态,令
特别地,叶子节点的
解释:
- 一个子树让它的父亲叛变的条件需要都满足(子树叛变,并且
要小于该子树所占的比例),所以取 - 全部叛变最大的
,所以取 取 同理
P3195 [HNOI2008] 玩具装箱 [普通DP] [斜率优化] [省选/NOI-]
斜率优化板子
P2120 [ZJOI2007] 仓库建设 [普通DP] [斜率优化] [省选/NOI-]
斜率优化,然后有一些点需要注意
- 在末尾可能有
的无效工厂,这些工厂不需要在 点额外建造一个仓库; - 有可能全部工厂都是无效工厂,注意特判边界;
- 斜率优化有条件的请使用叉积,如果用除法请注意分母为
的情况; long double
能够帮助你解决一部分掉精度的问题,当然本题不一定需要;
P2490 [SDOI2011]黑白棋 [博弈论] [计数DP] [组合数] [省选/NOI-]
K-nim游戏 即给你
我们将所有数进行二进制拆分,每一位上的和为
prove:
如果所有的
都为 ,则一次操作肯定会使得某些数位上的 值改变。又因为一堆石子每位上都是 或 ,所以变动的绝对值不会超过 。因此操作结束后该位置上的 必不能为 。
否则,另一名玩家一定可以通过一次操作将所有的变成
这道题,不一样的是,最后取的为失败,那么我们就设
然后该怎么推怎么推啦!(不想写了逃)
P2605 [ZJOI2010]基站选址 [普通DP] [线段树优化] [NOI/NOI+/CTSC]
P6563 [SBCOI2020] 一直在你身旁 [区间DP] [单调队列优化] [省选/NOI-]
如果我有人一直在我身旁就好了(酸
考虑一眼区间DP
设计状态
那么我们可以知道
看数据范围,好像是
这个区间的枚举显然是不怎么变的,如果要变的话也只能是把
如果说把
如果只是从
如果只是从
加上
那么当
那么当
这样我们的循环也要变一下,先
P1131 [ZJOI2007] 时态同步 [数型DP?] [贪心] [提高+/省选-]
考虑不像DP,更像贪心
你知道,如果说在不改变到根节点距离最长的子节点的长度的情况下,改变的边的长度越深,方案越优
then,就贪心完了呗
void dfs(int u,int fa){ for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].to; if(v == fa) continue; dfs(v,u); dis[u] = max(dis[u],dis[v] + edge[i].val); } for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].to; if(v == fa) continue; ans += dis[u] - dis[v] - edge[i].val; } }
P2466 [SDOI2008] Sue 的小球 [区间DP] [预处理当前选择对将来选择的影响] [省选/NOI-]
这道题,一看就是一个区间DP,然后呢……(LXW停止运行,正在向HF报告错误
考虑,你显然要先排一遍序
然后可以设计状态:
考虑得分这个东西好像不太好搞,那么我们可以把最大得分改为最小失分
then,你可以发现一些奇妙的发现:
你并不能确定
预前处理当前选择对将来选择的影响!
比如说,你从
- 在你移动的这段时间里,
和 的所有彩蛋都会减少一些分数,这些分数即是转移时需要加上的值
最后是一段核心转移code:
为了写起来方便,把
望知晓!!
f[i][j] = min(f[i][j],f[i+1][j] + (pre[i] - pre[0] + pre[n] - pre[j]) * (ball[i+1].x - ball[i].x)); f[i][j] = min(f[i][j],g[i+1][j] + (pre[i] - pre[0] + pre[n] - pre[j]) * (ball[j].x - ball[i].x)); g[i][j] = min(g[i][j],g[i][j-1] + (pre[i-1] - pre[0] + pre[n] - pre[j-1]) * (ball[j].x - ball[j-1].x)); g[i][j] = min(g[i][j],f[i][j-1] + (pre[i-1] - pre[0] + pre[n] - pre[j-1]) * (ball[j].x - ball[i].x));
P2607 [ZJOI2008] 骑士 [树型DP] [基环树] [省选/NOI-]
就是上司的舞会(树型DP),然后多了你要有很多判环,反正是一道基环树DP板子,看看题解即可。
本文来自博客园,作者:ricky_lin,转载请注明原文链接:https://www.cnblogs.com/rickylin/p/17237097.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步