1. 动态规划基础与Floyd-Warshall算法概述
动态规划(Dynamic Programming)作为算法设计中的核心思想,其价值在于将看似复杂的问题拆解为可管理的子问题。这种思想最早由Richard Bellman在1950年代提出,最初用于解决多阶段决策问题。在计算机科学领域,动态规划已成为解决最优化问题的利器。
Floyd-Warshall算法是动态规划在图论中的经典应用,由Robert Floyd和Stephen Warshall在1962年分别独立提出。该算法能高效计算出加权图中所有顶点对之间的最短路径,时间复杂度为O(n³),适用于包含负权边(但不含负权回路)的图结构。
注意:虽然Dijkstra算法也能计算最短路径,但Floyd-Warshall的优势在于它能一次性计算出所有顶点对的最短路径,且实现代码极其简洁。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动态规划的核心特征解析
2.1 重叠子问题特性
在实际编码中,重叠子问题表现为递归调用时的重复计算。以斐波那契数列为例,计算fib(5)时需要重复计算fib(3)等子问题。动态规划通过存储中间结果(记忆化)来避免这种重复计算。
go复制// 传统递归斐波那契(存在大量重复计算)
func fib(n int) int {
if n <= 1 { return n }
return fib(n-1) + fib(n-2)
}
// 动态规划版本(自底向上)
func fibDP(n int) int {
dp := make([]int, n+1)
dp[0], dp[1] = 0, 1
for i := 2; i <= n; i++ {
dp[i] = dp[i-1] + dp[i-2]
}
return dp[n]
}
2.2 最优子结构特性
最优子结构意味着全局最优解包含子问题的最优解。以Floyd-Warshall算法为例,顶点i到j的最短路径要么是直接相连的边,要么是通过某个中间顶点k的路径(即i→k→j),而i→k和k→j本身也必须是各自的最短路径。
3. Floyd-Warshall算法深度解析
3.1 算法核心思想
算法采用三重循环结构,逐步构建最短路径矩阵:
- 初始化距离矩阵dist,其中dist[i][j]表示顶点i到j的直接距离
- 对于每个中间顶点k,检查是否通过k能使i到j的路径更短
- 通过动态更新dist矩阵,最终得到所有顶点对的最短距离
go复制for k := 0; k < V; k++ {
for i := 0; i < V; i++ {
for j := 0; j < V; j++ {
if dist[i][k] + dist[k][j] < dist[i][j] {
dist[i][j] = dist[i][k] + dist[k][j]
}
}
}
}
3.2 Go语言实现细节
在Go实现中,我们需要注意几个关键点:
- 使用math.Inf(1)表示初始的无限大距离
- 图的表示采用邻接表形式([][]FloydGra
