一. 请写出作业“算法第三章3”中题目“7-4 最低通行费”的动态规划方程
(1)状态表示
设 dp[i][j]
表示商人到达网格位置 (i, j)
时的最小费用。题目中规定了必须在 (2N-1)
个单位时间内穿越出去,因为每一步的移动都会增加1个单位时间,所以只关注最终到达右下角 (N-1, N-1)
的最小费用就行。
(2)状态方程
根据N*N方格每个数的位置考虑位置dp[i][j]可以从左边或者上边过来。
if (i > 0) {
dp[i][j] = min(dp[i][j], dp[i-1][j] + grid[i][j]);
}
if (j > 0) {
dp[i][j] = min(dp[i][j], dp[i][j-1] + grid[i][j]);
}
grid[i][j]表示网格位置 (i, j)
的费用。
(3)边界条件
初始时,商人位于左上角 (0, 0)
,因此 dp[0][0] = grid[0][0]
。
同时,由于不能超出网格边界,因此在状态转移时,需要确保 i>=0
, i<N
, j>=0
, j<N
。
(4)时间、空间复杂度分析
-
时间复杂度:由于每个网格位置
(i, j)
都需要从两个或者一个方向进行状态转移,总共有N×N
个网格位置,因此时间复杂度为O(N^2)
。 -
空间复杂度:需要存储每个网格位置的最小费用,因此空间复杂度为
O(N^2)
。
综上所述,通过动态规划的方法,我们可以在 O(N^2)
的时间和空间复杂度内解决该问题。
(5)代码
#include<bits/stdc++.h>
using namespace std;
int main() {
int N;
cin >> N;
vector<vector<int>> grid(N, vector<int>(N));
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
cin >> grid[i][j];
}
}
vector<vector<int>> dp(N, vector<int>(N, INT_MAX));
dp[0][0] = grid[0][0];
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
if (i > 0) {
dp[i][j] = min(dp[i][j], dp[i-1][j] + grid[i][j]);
}
if (j > 0) {
dp[i][j] = min(dp[i][j], dp[i][j-1] + grid[i][j]);
}
}
}
int minCost = dp[N-1][N-1];
cout << minCost << endl;
return 0;
}
二 .结合本章的学习,总结你对动态规划法的体会和思考
动态规划是一种解决最优化问题的算法设计范式,适用于那些具有重叠子问题和最优子结构性质的问题。通过将问题分解为更小的子问题,并存储这些子问题的解以避免重复计算,动态规划能够显著提高算法的效率。
算法流程主要为:问题分解与状态表示/状态转移方程/边界条件/优化与存储/递归与迭代