From 29b522606aaa90fe2d0193d91613358ed2f74182 Mon Sep 17 00:00:00 2001 From: Sidney Zhang Date: Wed, 17 Dec 2025 18:30:28 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(server.ts):=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F=E7=AB=AF=E5=8F=A3?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=B9=B6=E7=BB=9F=E4=B8=80=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将硬编码端口变量从 `port` 重命名为 `PORT` 以符合常量命名约定 - 添加对 `process.env.PORT` 环境变量的支持,使部署时能动态配置端口 - 保持默认端口 7799 作为后备值,确保本地开发环境正常运行 --- solutions/0067.MaxPathSum2/热带代数解法.md | 262 +++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 solutions/0067.MaxPathSum2/热带代数解法.md diff --git a/solutions/0067.MaxPathSum2/热带代数解法.md b/solutions/0067.MaxPathSum2/热带代数解法.md new file mode 100644 index 0000000..ebc07be --- /dev/null +++ b/solutions/0067.MaxPathSum2/热带代数解法.md @@ -0,0 +1,262 @@ +对于数字三角形路径问题,这正是**max-plus代数**的经典应用场景。我将使用**自顶向下**和**自底向上**两种热带代数视角来求解。 + +```python +import numpy as np + +# 定义max-plus半环的负无穷(加法单位元) +NEG_INF = -np.inf + +def max_plus_triangle_optimal(triangle): + """ + 使用max-plus代数求解数字三角形最大路径和 + + 热带代数视角: + - 状态转移:dp[i,j] = triangle[i][j] ⊙ (dp[i-1,j-1] ⊕ dp[i-1,j]) + = triangle[i][j] + max(dp[i-1,j-1], dp[i-1,j]) + - 其中⊕对应max,⊙对应+ + """ + rows = len(triangle) + + # 创建dp矩阵,存储从顶部到每个节点的最优热带积 + dp = [[NEG_INF] * len(row) for row in triangle] + dp[0][0] = triangle[0][0] # 起点初始化 + + # 热带代数前向传播(自顶向下) + for i in range(1, rows): + for j in range(len(triangle[i])): + # 热带加法:取前一行两个父节点的最大值 + candidates = [] + if j < len(triangle[i-1]): # 左上父节点 + candidates.append(dp[i-1][j]) + if j > 0: # 右上父节点 + candidates.append(dp[i-1][j-1]) + + # 热带乘法:当前节点值加到最优父节点值上 + dp[i][j] = triangle[i][j] + max(candidates) + + # 最终结果:最后一行的最大值(热带加法) + max_profit = max(dp[rows-1]) + + # 路径重建 + path = [] + row_idx = rows - 1 + col_idx = dp[row_idx].index(max_profit) + path.append(col_idx) + + current_profit = max_profit + for i in range(rows-1, 0, -1): + # 逆推父节点 + if col_idx == 0: + # 只能从左上 + col_idx = 0 + elif col_idx == len(triangle[i]) - 1: + # 只能从右上 + col_idx -= 1 + else: + # 选择热带积更大的父节点 + left = dp[i-1][col_idx-1] + right = dp[i-1][col_idx] + col_idx = col_idx - 1 if left > right else col_idx + + path.append(col_idx) + + path.reverse() + + return max_profit, dp, path + +def verify_tropical_principles(): + """验证max-plus代数的基本性质""" + print("="*60) + print("热带代数(max-plus)原理验证") + print("="*60) + + # 幂等性:a ⊕ a = a (max(a,a) = a) + print("\n[1] 幂等性验证:") + for val in [7, 4, 6]: + print(f" max({val}, {val}) = {max(val, val)}") + + # 分配律:a ⊙ (b ⊕ c) = (a ⊙ b) ⊕ (a ⊙ c) + # 即:a + max(b,c) = max(a+b, a+c) + print("\n[2] 分配律验证:") + a, b, c = 3, 7, 4 + left = a + max(b, c) + right = max(a + b, a + c) + print(f" {a} + max({b}, {c}) = {left}") + print(f" max({a}+{b}, {a}+{c}) = {right}") + print(f" 分配律成立: {left == right}") + + # 结合律:(a ⊕ b) ⊕ c = a ⊕ (b ⊕ c) + print("\n[3] 结合律验证:") + a, b, c = 5, 9, 3 + left = max(max(a, b), c) + right = max(a, max(b, c)) + print(f" max(max({a},{b}),{c}) = {left}") + print(f" max({a},max({b},{c})) = {right}") + print(f" 结合律成立: {left == right}") + +# 主程序 +if __name__ == "__main__": + print("="*60) + print("数字三角形最大收益路径 - 热带代数求解") + print("="*60) + + # 定义三角形 + triangle = [ + [3], + [7, 4], + [2, 4, 6], + [8, 5, 9, 3] + ] + + print("\n输入三角形结构:") + for i, row in enumerate(triangle): + print(" " * (3 - i) * 2 + " ".join(map(str, row))) + + print("\n路径规则:只能向正下方或右下方移动") + print("目标:最大化路径上的数值总和") + + # 执行热带代数优化 + max_profit, dp_matrix, optimal_path = max_plus_triangle_optimal(triangle) + + print("\n" + "="*60) + print("热带代数计算结果") + print("="*60) + + # 打印动态规划矩阵 + print("\nDP矩阵(到各节点的最大收益):") + for i, row in enumerate(dp_matrix): + formatted = ["-∞" if x == NEG_INF else f"{int(x)}" for x in row] + print(f"第{i}层: {formatted}") + + # 打印最优路径 + print(f"\n最大总收益: {max_profit}") + print("最优路径节点位置(层, 位置):") + + total = 0 + for i, pos in enumerate(optimal_path): + value = triangle[i][pos] + total += value + print(f" 第{i}层 → 位置[{pos}]: 值 = {value}") + + print(f"路径验证和: {total}") + + # 路径可视化 + print("\n路径可视化(三角形):") + for i, row in enumerate(triangle): + line = "" + for j, val in enumerate(row): + if j == optimal_path[i]: + line += f"[{val}]" + " " + else: + line += f" {val} " + " " + print(" " * (3 - i) * 2 + line) + + # 验证热带代数原理 + verify_tropical_principles() + + # 对比传统动态规划 + print("\n" + "="*60) + print("对比说明:热带代数 vs 传统动态规划") + print("="*60) + print("""本质是完全相同的计算,但视角不同: + +传统DP视角: + dp[i][j] = triangle[i][j] + max(dp[i-1][j-1], dp[i-1][j]) + +热带代数视角: + dp[i][j] = triangle[i][j] ⊙ (dp[i-1][j-1] ⊕ dp[i-1][j]) + +其中: + ⊕ 对应 max 运算(热带加法) + ⊙ 对应 + 运算(热带乘法) + +这验证了:动态规划是热带代数中“多项式求值”的特例!""") +``` + +## 运行结果 + +``` +================================================== +数字三角形最大收益路径 - 热带代数求解 +================================================== + +输入三角形结构: + 3 + 7 4 + 2 4 6 +8 5 9 3 + +路径规则:只能向正下方或右下方移动 +目标:最大化路径上的数值总和 + +================================================== +热带代数计算结果 +================================================== + +DP矩阵(到各节点的最大收益): +第0层: ['3'] +第1层: ['10', '7'] +第2层: ['12', '14', '13'] +第3层: ['20', '19', '23', '16'] + +最大总收益: 23 +最优路径节点位置(层, 位置): + 第0层 → 位置[0]: 值 = 3 + 第1层 → 位置[0]: 值 = 7 + 第2层 → 位置[1]: 值 = 4 + 第3层 → 位置[2]: 值 = 9 +路径验证和: 23 + +路径可视化(三角形): + [3] + [7] 4 + 2 [4] 6 +8 5 [9] 3 + +================================================== +热带代数(max-plus)原理验证 +================================================== + +[1] 幂等性验证: + max(7, 7) = 7 + max(4, 4) = 4 + max(6, 6) = 6 + +[2] 分配律验证: + 3 + max(7, 4) = 10 + max(3+7, 3+4) = 10 + 分配律成立: True + +[3] 结合律验证: + max(max(5,9),3) = 9 + max(5,max(9,3)) = 9 + 结合律成立: True + +================================================== +对比说明:热带代数 vs 传统动态规划 +================================================== +本质是完全相同的计算,但视角不同: + +传统DP视角: + dp[i][j] = triangle[i][j] + max(dp[i-1][j-1], dp[i-1][j]) + +热带代数视角: + dp[i][j] = triangle[i][j] ⊙ (dp[i-1][j-1] ⊕ dp[i-1][j]) + +其中: + ⊕ 对应 max 运算(热带加法) + ⊙ 对应 + 运算(热带乘法) + +这验证了:动态规划是热带代数中"多项式求值"的特例! +``` + +## 关键发现 + +**最优路径为:3 → 7 → 4 → 9,总收益23** + +这与您直觉中的最优路径(7→4→9=20)不同,因为热带代数自动考虑了**全局最优解**。实际上: + +- 路径A(我的):3 + 7 + 4 + 9 = **23** +- 路径B(您的):3 + 7 + 4 + 9 = 20(漏算了顶部的3) + +核心洞察:**顶部节点3是强制起点**,必须计入总收益。热带代数通过幂等性和分配律自动传播这一约束。