动态规划——DP的转化 学习笔记
动态规划——DP的转化 学习笔记(待更)
动态规划与最短路
例题:P2761 软件补丁问题,很容易写出转移方程:\(dp_s \leftarrow dp_{s \setminus F_1 \cup F_2} + t_i\),
但是这样就出现了环,没有形成 DAG 就无法跑动态规划了,怎么办?
可以将原问题转换为[最短路]:
将原状态 \(s\) 记为一个点,将原转移路径记为一条边 \((s, s')\),然后跑最短路即可。
这种问题的转移方程,形如:\(f_v = f_u + w\),即有边 \((u \rightarrow v, w)\)。
当然前提是状态数不能太多,因为最短路的复杂度为 \(O(n ^ 2)\),或 \(O(m \log n)\),根据情况选择。
代码:
typedef pair<int, int> PII; const int N = 21, M = 110; int n, m, t[M]; int b1[M], b2[M], f1[M], f2[M]; int cuse(int s, int i) { if ((s & b1[i]) == b1[i] && (s & b2[i]) == 0) return (s & ~f1[i]) | f2[i]; return -1; } int dis[1 << N]; bool st[1 << N]; int dijkstra(int s, int e) { memset(dis, 0x3f, sizeof dis); const int INF = dis[0]; priority_queue<PII, vector<PII>, greater<PII>> heap; dis[s] = 0; heap.push({0, s}); while (heap.size()) { int u = heap.top().second, d = heap.top().first, v; heap.pop(); if (st[u]) continue; st[u] = true; for (int i = 0; i < m; ++i) { if ((v = cuse(u, i)) == -1) continue; if (dis[v] > d + t[i]) { dis[v] = d + t[i]; heap.push({dis[v], v}); } } } return dis[e] == INF ? 0 : dis[e]; } signed main() { n = ur, m = ur; char b[N], f[N]; for (int i = 0; i < m; ++i) { t[i] = ur; scanf("%s %s", b, f); for (int j = 0; j < n; ++j) { if (b[j] == '+') b1[i] |= 1 << j; else if (b[j] == '-') b2[i] |= 1 << j; if (f[j] == '-') f1[i] |= 1 << j; else if (f[j] == '+') f2[i] |= 1 << j; } } printf("%lld\n", dijkstra((1 << n) - 1, 0)); return 0; }
动态规划与高斯消元
线性动态规划有时会转移成环,例如:
\[\begin{array}{l}
f_1=k_{12}f_2+k_{13}f_3+k_{14}f_4+\dots\\
f_2=k_{21}f_1+\dots\\
\dots
\end{array}
\]
此时可以高斯消元解决。
本文来自博客园,作者:RainPPR,转载请注明原文链接:https://www.cnblogs.com/RainPPR/p/dp-transformation.html
如有侵权请联系我(或 2125773894@qq.com)删除。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战