NOIP 前 dp 做题小记
NOIP 前 dp 做题小记
-
设 表示在前 个城堡中总共派遣 个士兵时,可以获得的最大分数。
初始化:,
答案统计:
转移:。其中 表示向第 个城堡派遣 个士兵能获得的分数。这里就是在枚举在第 个城堡中投入的兵力 来转移。
(,)可以在 的时间内预处理:
for(int i = 1; i <= n; i++) { deque<int> tmp; for(int j = 1; j <= s; j++) tmp.push_back(a[j][i]); sort(tmp.begin(), tmp.end()); int cnt = 0; for(int j = 0; j <= m; j++) { while(!tmp.empty() && j > tmp.front() * 2) { cnt++; tmp.pop_front(); } g[i][j] = cnt * i; } }
时间复杂度分析:预处理 花费 ,dp 状态数 ,单次转移的时间复杂度为 ,总时间复杂度为 (忽略了预处理的时间复杂度,因为不是瓶颈)。可以获得 40 分。
优化:
从决策的角度来考虑。向第 个城堡投入兵力时,并不是每多派遣一个士兵,在此城堡中获得的分数都会增加。设 表示向第 投入兵力第 多的人派遣的士兵的数量(与上文的 的含义不同),则我方投入的兵力只有在恰好达到某个 时,在此城堡上得到的分数才会增加。这启发我们转移时不是枚举向城堡中投入的人数,而是枚举要超过多少人的兵力的两倍。这样转移的时间复杂度就从 降到了 ,总时间复杂度降到 ,可以通过。
另一种思考方法是把问题转化为分组背包问题。按城堡来分组,每个组有 个物品,第 组第 个物品代表我方在第 个城堡中打败了 个人,据此可以得出其花费为 ,价值为 。
-
注意“子序列”不一定是连续的。
-
做法
设 表示以第 个元素结尾的最长合法子序列的长度,显然
-
做法
从位运算的角度出发。
设 表示结尾元素的第 个二进制位为 时,最长的合法子序列的长度。
计算 时,枚举 的第 位二进制位为 的 ,用 来更新 ,然后再反过来用 来更新 。
for(int i = 0; i < n; i++) { int tmp = 0; for(int j = 0; (1 << j) <= a[i]; j++) if(a[i] & (1 << j)) tmp = max(tmp, f[j] + 1); for(int j = 0; (1 << j) <= a[i]; j++) if(a[i] & (1 << j)) f[j] = tmp; ans = max(ans, tmp); }
-
-
题意:给定一棵树,每个节点 有费用和权值。选择一个包含根节点且有 个点的连通块,使得节点总权值与总费用的比最大。
-
题意:求基环树的最大带权独立集。
树上最大带权独立集是树形 dp 经典题目:没有上司的舞会。回忆一下做法:设 分别表示选/不选 时,在 中能获得的最大权值。转移方程如下:
而在这道题中,图多了一条边,形成了一棵基环树。如何转化到树上问题呢?
由于基环树有且只有一个环,因此删去环上的任意一条边后,基环树就变成了真正的树。不妨假设删去的边是 ,我们在删完边后的图上做树形 dp 求树上最大带权独立集。但考虑到删去的边的限制, 和 这两个节点不能同时选择,这需要在 dp 中有所体现。
修改是不难的:只需分别以 和 为根各做一次树形 dp,则答案为 。这相当于分别钦定了不选择 或不选择 ,这样得到的答案一定合法,并且是考虑周全的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】