当前位置: 首页 > news >正文

DAG的DP(UVA437 巴比伦塔 The Tower of Babylon)

DAG 上的 DP 知识点

DAG 的基本概念

DAG 是一种没有环路的有向图,具有拓扑序特性。动态规划在 DAG 上的应用通常基于拓扑序或记忆化搜索。(像我这种暂时还没学过拓扑排序的可以用dfs+记忆化搜索)

DAG 上 DP 的核心思想

  1. 状态定义:将问题抽象为 DAG 上的节点,状态转移对应图中的边。
  2. 状态转移:根据拓扑序或记忆化搜索,逐步更新状态值。
  3. 初始化:明确边界条件(如起点或终点的状态值)。

常见问题类型

  1. 最长路径问题:求解 DAG 中从起点到终点的最长路径。
  2. 最短路径问题:求解 DAG 中从起点到终点的最短路径。
  3. 依赖关系问题:如任务调度、课程安排等具有依赖关系的场景。

实现方法

 方法 1:记忆化搜索

通过递归和缓存中间结果实现 DP。

#include <vector>
#include <cstring>
using namespace std;const int N = 1000;
vector<int> adj[N];
int memo[N];int dfs(int u) {if (memo[u] != -1) return memo[u];int res = 0;for (int v : adj[u]) {res = max(res, dfs(v) + 1);}return memo[u] = res;
}void dag_dp(int n) {memset(memo, -1, sizeof(memo));for (int i = 0; i < n; ++i) {if (memo[i] == -1) dfs(i);}
}
方法 2:拓扑排序 + DP
  1. 拓扑排序:使用 Kahn 算法或 DFS 生成拓扑序。
  2. DP 更新:按拓扑序依次更新每个节点的状态值。
#include <vector>
#include <queue>
using namespace std;const int N = 1000;
vector<int> adj[N];  // 邻接表
int in_degree[N];    // 入度数组
int dp[N];           // DP 数组void dag_dp(int n) {queue<int> q;for (int i = 0; i < n; ++i) {if (in_degree[i] == 0) {q.push(i);dp[i] = 0;  // 初始化起点状态}}while (!q.empty()) {int u = q.front();q.pop();for (int v : adj[u]) {dp[v] = max(dp[v], dp[u] + 1);  // 状态转移if (--in_degree[v] == 0) {q.push(v);}}}
}
注意事项
  1. 拓扑序的正确性:确保 DAG 的拓扑序生成无误。
  2. 初始状态:明确起点或终点的初始化条件。
  3. 状态转移方程:根据问题设计合理的转移逻辑。

UVA437 巴比伦塔 The Tower of Babylon

思路:

dfs+记忆化搜索

解题思路

  1. 数据预处理

    • 每个箱子的长、宽、高被读取并存储在数组x[]y[]z[]中。
    • 通过交换操作确保每个箱子的三个维度按升序排列,即x[i] ≤ y[i] ≤ z[i],这样便于后续处理。
  2. 动态规划定义

    • dp[i][w]表示以第i个箱子的第w种摆放方式作为顶部时的最大高度。
    • w的取值(0、1、2)对应箱子的不同摆放方式:
      • w=0:以x[i]为高度,底面为y[i] × z[i]
      • w=1:以y[i]为高度,底面为x[i] × z[i]
      • w=2:以z[i]为高度,底面为x[i] × y[i]
  3. 递归函数dfs

    • 记忆化搜索实现动态规划,避免重复计算。
    • 对于当前箱子i的摆放方式w,遍历所有其他箱子j的每种摆放方式k,检查是否可以将j放在i的下方。
    • 如果满足条件,更新dp[i][w]为当前值与dfs(j, k)中的较大值。
  4. 边界条件

    • 如果dp[i][w]已被计算过,直接返回其值。
    • 最终,dp[i][w]加上当前摆放方式的高度(x[i]y[i]z[i])。
  5. 主函数逻辑

    • 循环处理多个测试用例,直到输入n=0时结束。
    • 对每个测试用例,初始化dp数组为0,然后遍历所有箱子的每种摆放方式,调用dfs计算最大高度。
    • 输出每个测试用例的最大高度。

关键函数说明

  • panduan(i, w, j, k)
    检查箱子j的摆放方式k是否可以放在箱子i的摆放方式w下方。具体逻辑是检查j的底面长和宽是否严格小于i的底面长和宽。

  • dfs(i, w)
    递归计算以箱子i的摆放方式w作为顶部时的最大高度。通过记忆化避免重复计算,确保时间复杂度为O(n²)。

复杂度分析

  • 时间复杂度:O(n²),每个箱子最多被处理3次(对应3种摆放方式),每次处理需要遍历其他所有箱子的3种摆放方式。
  • 空间复杂度:O(n),dp数组的大小为n × 3
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<bits/stdc++.h>
#define ll long long 
using namespace std;
int n;
int x[35], y[35], z[35];
int dp[100][3];
bool panduan(int i, int w, int j, int k) {int l, r, u, v;l = (w == 0 ? y[i] : x[i]);r = (w == 2 ? y[i] : z[i]);u = (k == 0 ? y[j] : x[j]);v = (k == 2 ? y[j] : z[j]);if (u < l && v < r) {return true;}else {return false;}
}
int dfs(int i, int w) {if (dp[i][w] != 0) {return dp[i][w];}for (int j = 0; j < n; j++) {for (int k = 0; k <= 2; k++) {if (panduan(i, w, j, k)) {dp[i][w] = max(dp[i][w], dfs(j, k));}}}if (w == 0) {dp[i][w] += x[i];}else if (w == 1) {dp[i][w] += y[i];}else {dp[i][w] += z[i];}return dp[i][w];
}
int main(){ios::sync_with_stdio(false);        // 禁用同步cin.tie(nullptr);                   // 解除cin与cout绑定int ans = 0;while (true) {ans++;cin >> n;if (n == 0) {return 0;}for (int i = 0; i < n; i++) {cin >> x[i] >> y[i] >> z[i];if (x[i] > y[i]) {swap(x[i], y[i]);}if (x[i] > z[i]) {swap(x[i], z[i]);}if (y[i] > z[i]) {swap(y[i], z[i]);}}memset(dp, 0, sizeof(dp));int r = 0;for (int i = 0; i < n; i++) {r = max(r, dfs(i, 0));r = max(r, dfs(i, 1));r = max(r, dfs(i, 2));}cout << "Case " << ans << ": maximum height = " << r << endl;}return 0;
}

可以参考该网站DAG 上的 DP - OI Wiki

http://www.dtcms.com/a/343612.html

相关文章:

  • Java—— 网络编程
  • 具身导航近期论文分享(一)
  • 华清远见25072班数据结构学习day1
  • 【时时三省】集成测试 简介
  • GIS在城乡供水一体化中的应用
  • c#语言的学习【02,函数重载】
  • Java数据类型全解析:从基础到进阶的完整指南
  • leetcode-python-349两个数组的交集
  • 快速了解图像形态学
  • Huggingface 的介绍,使用
  • 人体生理参数信号采集项目——心电信号
  • actuary notes[4]
  • git 冲突解决方案
  • 组件卸载时useEffect状态
  • 人工智能驱动的现代电商前端开发:从基础到智能体验
  • 网易测试岗位--面试真题分析
  • 利用 Java 爬虫获取淘宝商品评论实战指南
  • 大语言模型原理(Transformer架构)
  • 高可用操作步骤
  • FP4层与NF4层 4位量化总结(49)
  • 实践题:数据采集与处理培训大纲
  • JavaWeb(五)转发、重定向、Get、POST
  • 在JAVA中如何给Main方法传参?
  • java开发面试题(提高篇)
  • 2026 济南玉米及淀粉深加工展:从原料到创新产品的完整解决方案
  • 【算法精练】 哈夫曼编码
  • Eino 框架组件协作指南 - 以“智能图书馆建设手册”方式理解
  • Excel中运行VB的函数
  • Sklearn 机器学习 房价预估 线性回归模型实现预估
  • 【自用】JavaSE--网络通信