7-4 最低通行费
一个商人穿过一个N×N的正方形的网格,去参加一个非常重要的商务活动。他要从网格的左上角进,右下角出。每穿越中间1个小方格,都要花费1个单位时间。商人必须在(2N-1)个单位时间穿越出去。而在经过中间的每个小方格时,都需要缴纳一定的费用。
这个商人期望在规定时间内用最少费用穿越出去。请问至少需要多少费用?
注意:不能对角穿越各个小方格(即,只能向上下左右四个方向移动且不能离开网格)。
输入格式:
第一行是一个整数,表示正方形的宽度N (1≤N<100);
后面N行,每行N个不大于100的整数,为网格上每个小方格的费用。
输出格式:
至少需要的费用。
#include<iostream>
using namespace std;
#include<bits/stdc++.h>
int main()
{
int n;
cin>>n;
int v[101][101];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>v[i][j];
}
}
int dp[101][101];
memset(dp,0x3f,sizeof dp);
dp[1][1]=v[1][1];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
dp[i][j]=min(dp[i][j],dp[i-1][j]+v[i][j]);
dp[i][j]=min(dp[i][j],dp[i][j-1]+v[i][j]);
}
}
cout<<dp[n][n];
return 0;
}
-
输入网格:首先,代码读取一个
n x n的网格,并将每个点的值存储在二维数组v中。 -
初始化动态规划数组:然后,代码初始化一个同样大小的二维数组
dp,用于存储动态规划过程中的中间结果。dp[i][j]表示到达网格中点(i, j)的最短路径长度。memset函数用于将dp数组的所有元素初始化为一个非常大的值(0x3f),这代表一个“无穷大”的状态,表示在初始化时,任何点的最短路径都是未知的。 -
设置起点:将起点
dp[1][1]设置为v[1][1],即网格左上角的值。 -
填充动态规划数组:接下来,代码使用两层嵌套循环遍历整个网格。对于每个点
(i, j),代码尝试从上方(i-1, j)和左方(i, j-1)到达该点,并更新dp[i][j]为这两个值中的最小值加上当前点的值v[i][j]。这样,dp[i][j]就存储了从起点到点(i, j)的最短路径长度。 -
输出结果:最后,代码输出
dp[n][n],即到达网格右下角的最短路径长度。
状态表示:状态 dp[i][j] 表示从网格的左上角 (1,1) 到达当前格子 (i,j) 的最短路径和
状态方程:
dp[i][j] = min(dp[i][j], dp[i-1][j] + v[i][j]):从上方到达格子(i,j)的最短路径和。dp[i][j] = min(dp[i][j], dp[i][j-1] + v[i][j]):从左方到达格子(i,j)的最短路径和。
边界条件:
dp[1][1] = v[1][1]:起点的最短路径和就是其自身的值。
时间空间复杂度分析:O(n^2) O(n^2)
动态规划法的体会和思考
1. 重叠子问题
动态规划算法通常用于解决那些具有重叠子问题特性的问题。这意味着在递归算法中,相同的子问题会被多次求解。通过存储这些子问题的解(通常是在表格中),可以避免重复计算,从而提高效率。
2. 最优子结构
如果一个问题的最优解包含其子问题的最优解,那么这个问题就具有最优子结构。这是动态规划能够适用的另一个关键特性。
3. 状态和状态转移
- 状态:在动态规划中,状态通常代表问题在某个点的特定情况或配置。
- 状态转移方程:这是动态规划中的核心,它定义了如何从一个状态转移到另一个状态,并结合子问题的解来构建原问题的解。
4. 边界条件
在动态规划中,必须明确定义问题的边界条件。这些边界条件通常对应于递归的基本情况,是递归结束的信号。
5. 记忆化(Memoization)
记忆化是一种自顶向下的方法,用于存储已经计算过的子问题的结果,以避免重复计算。这通常用于递归实现中。
6. 表格法(Tabulation)
表格法是一种自底向上的方法,用于填充一个表格(通常是数组或矩阵),其中每个条目代表一个子问题的解。这种方法通常用于迭代实现中。
7. 时间复杂度和空间复杂度
动态规划通常需要额外的空间来存储中间结果,这可能导致较高的空间复杂度。然而,通过避免重复计算,它可以显著降低时间复杂度。
8. 适用问题类型
动态规划适用于多种问题类型,包括但不限于:
- 最短路径问题(如最短路径、最小生成树)
- 计数问题(如组合问题、排列问题)
- 最优搜索问题(如背包问题、旅行商问题)
- 序列问题(如编辑距离、最长公共子序列)
9. 优化技巧
- 空间优化:通过使用滚动数组或其他技术减少存储空间的需求。
- 状态压缩:在状态空间很大时,通过减少状态的表示来减少空间复杂度。
10. 实现注意事项
- 确保状态转移方程正确无误。
- 仔细考虑所有可能的状态和转移。
- 测试边界条件和特殊情况。

263

被折叠的 条评论
为什么被折叠?



