Page Top

动态规划——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} \]

此时可以高斯消元解决。

posted @   RainPPR  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示