3 条题解

  • 5
    @ 2023-12-3 0:52:53

    这是本蒟蒻第二次写解析🚀️ 🚀️🚀️:

    当我们遇到一个动态规划问题时,通常需要定义一个二维数组来存储中间结果。在这个问题中,我们使用了一个二维数组 f 来保存每个位置的最大值。

    首先,我们通过输入函数获取矩阵的行数和列数,并创建一个大小为 nm 列的矩阵 a 来存储输入的数据。接下来,我们创建一个大小相同的二维数组 f,并将所有元素初始化为 0。

    然后,我们将矩阵 a 的第一个元素赋值给 f 的第一个元素,即 f[0][0] = a[0][0]。这是因为在起点处,路径的最大和就是起点的值。

    接下来,我们使用两个嵌套的循环遍历整个矩阵 a。对于每个位置 (i, j),我们根据其相邻位置的最大值来计算当前位置的最大值。

    如果 i == 0j == 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])
    

    欢迎━(`∀´)ノ亻!个位大佬给与点评!!!😄

    • @ 2024-3-10 20:08:18

      《有点向上》

    • @ 2024-3-26 20:42:59
      #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(i == 1&&j == 1)continue;
      f[i][j]=max(f[i-1][j],f[i][j-1])+a[i][j];
      }
      }
      cout<<f[n][m];
      
      }
      
    • @ 2024-3-26 20:43:34
      #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(i == 1&&j == 1)continue;
      f[i][j]=max(f[i-1][j],f[i][j-1])+a[i][j];
      }
      }
      cout<<f[n][m];
      
      }
      

      @

  • 1
    @ 2023-12-16 10:15:58
    思路

    这是一道比较简单的动态规划问题。

    定义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
      @ 2023-10-6 17:06:18
      思路 (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];
      

      }

      • @ 2023-10-15 20:51:44

        有陷阱!是这个代码:

        #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(i == 1&&j == 1)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
    上传者