3 条题解
-
5
这是本蒟蒻第二次写解析🚀️ 🚀️🚀️:
当我们遇到一个动态规划问题时,通常需要定义一个二维数组来存储中间结果。在这个问题中,我们使用了一个二维数组
f
来保存每个位置的最大值。首先,我们通过输入函数获取矩阵的行数和列数,并创建一个大小为
n
行m
列的矩阵a
来存储输入的数据。接下来,我们创建一个大小相同的二维数组f
,并将所有元素初始化为 0。然后,我们将矩阵
a
的第一个元素赋值给f
的第一个元素,即f[0][0] = a[0][0]
。这是因为在起点处,路径的最大和就是起点的值。接下来,我们使用两个嵌套的循环遍历整个矩阵
a
。对于每个位置(i, j)
,我们根据其相邻位置的最大值来计算当前位置的最大值。如果
i == 0
且j == 0
,表示当前位置是起点,我们不做任何操作,直接跳过。否则,我们进入以下判断:- 如果
i == 0
,表示当前位置在第一行,只能从左侧位置(i, j-1)
移动到当前位置(i, j)
,因此f[i][j] = f[i][j-1] + a[i][j]
。 - 如果
j == 0
,表示当前位置在第一列,只能从上方位置(i-1, j)
移动到当前位置(i, j)
,因此f[i][j] = f[i-1][j] + a[i][j]
。 - 否则,当前位置既可以从上方位置
(i-1, j)
移动到当前位置(i, j)
,也可以从左侧位置(i, j-1)
移动到当前位置(i, j)
。我们选择其中的最大值,并加上当前位置的值,即f[i][j] = max(f[i-1][j], f[i][j-1]) + a[i][j]
。
最后,我们输出
f[n-1][m-1]
,即矩阵右下角位置的值,这个值就是从起点到终点路径的最大和。这个算法的时间复杂度是 O(n * m),其中 n 是矩阵的行数,m 是矩阵的列数。这是因为我们需要遍历整个矩阵,并且每个位置的计算只需要常数时间。
☝上代码:(
当我打这几个字的时候感觉有点向上🥬) C++:#include <iostream> #include <vector> using namespace std; int main() { int n, m; cin >> n >> m; vector<vector<int>> a(n, vector<int>(m)); vector<vector<int>> f(n, vector<int>(m, 0)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> a[i][j]; } } f[0][0] = a[0][0]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (i == 0 && j == 0) { continue; } if (i == 0) { f[i][j] = f[i][j-1] + a[i][j]; } else if (j == 0) { f[i][j] = f[i-1][j] + a[i][j]; } else { f[i][j] = max(f[i-1][j], f[i][j-1]) + a[i][j]; } } } cout << f[n-1][m-1] << endl; return 0; }
py:
# 读入数据 n, m = map(int, input().split()) a = [list(map(int, input().split())) for _ in range(n)] # 初始化dp数组 f = [[0] * m for _ in range(n)] f[0][0] = a[0][0] # DP过程 for i in range(n): for j in range(m): if i == 0 and j == 0: continue if i == 0: f[i][j] = f[i][j-1] + a[i][j] elif j == 0: f[i][j] = f[i-1][j] + a[i][j] else: f[i][j] = max(f[i-1][j], f[i][j-1]) + a[i][j] # 输出结果 print(f[n-1][m-1])
欢迎━(`∀´)ノ亻!个位大佬给与点评!!!😄
- 如果
-
1
思路
这是一道比较简单的动态规划问题。
定义f[i][j]数组表示第i行第j列
注意这道题有陷阱,a[i][j]可以是负数,所以f数组开始应该赋值为负无穷
初始化:f[1][1]=a[1][1]
f[i][j]可以由它的上一行和左边转移过来,状态转移方程:
f[i][j]=max(f[i-1][j],f[i][j-1])+a[i][j];
输出f[n][m]
代码
#include <stdio.h> #include <iostream> using namespace std; int main(void){ register int n,m,**a,**f; scanf("%d%d",&n,&m); a=new int*[n+1]; f=new int*[n+1]; for(register int i=0;i<=n;i++){ a[i]=new int[m+1]; f[i]=new int[m+1]; for(register int j=0;j<=m;j++) f[i][j]=-100000; } for(register int i=1;i<=n;i++) for(register int j=1;j<=m;j++) scanf("%d",&a[i][j]); f[1][1]=a[1][1]; for(register int i=1;i<=n;i++) for(register int j=1;j<=m;j++) if(i!=1||j!=1) f[i][j]=max(f[i-1][j],f[i][j-1])+a[i][j]; printf("%d",f[n][m]); for(register int i=0;i<=n;i++){ delete a[i]; delete f[i]; } delete[] a; delete[] f; return 0; }
-
1
思路
(1)状态定义:显而易见,定义$f[i][j]$表示到达$a[i][j]$时取到的整数之和的最大值。 $\\$(2)状态初始化:相对比较简单,因为取的最大值,并且可能出现负数,所以需要将$f$数组初始化为一个极小值,之后将$f[1][1]$初始化为$a[1][1]$。 $\\$(3)状态转移方程:$a[i][j]$可以由$a[i-1][j]$和$a[i][j-1]$转移到,所以状态转移方程为: $\\f[i][j]=max(f[i-1][j],f[i][j-1])+a[i][j];$ $\\$(4)最终结果:$f[n][m]$代码
#include<bits/stdc++.h> using namespace std; const int N=1005; int n,m,a[N][N],f[N][N];
int main() { cin>>n>>m; memset(f,128,sizeof(f)); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cin>>a[i][j]; } } f[1][1]=a[1][1]; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(i1&&j1)continue; f[i][j]=max(f[i-1][j],f[i][j-1])+a[i][j]; }
} cout<<f[n][m];
}
- 1
信息
- ID
- 518
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 3
- 标签
- (无)
- 递交数
- 296
- 已通过
- 158
- 上传者