3 条题解

  • 0
    @ 2026-9-2 8:58:11

    感觉应该对2条路径走到一个点(重复点)处理方法不懂
    举例一个四维dp的里的做法(三维等解法的大佬不要嘲笑)

    首先,起点到终点走两次与题意是等效的。
    四位dp很容易想,但对于大佬题解里重复点的处理,蒟蒻实在是有点不太明白

    我们可以这样想,2条路径不相交,那么肯定一条在上面,一条在下面,如图是随便画的2条路径

    i,ji,j是红色路径的坐标,k,lk, l是黑色路径的坐标

    那么对于kk,我们只需枚举[i+1,m][i+1, m],ll只需枚举[1,j1][1,j-1]即可
    这样就不用判重啦

    由于最后dp不到终点,但其实黑色路径走到终点上方的点,红色路径走到终点左边的点就是答案,即f[m-1][n][m][n-1]

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    #define INF = 0x3f3f3f3f
    
    int a[51][51], f[51][51][51][51];
    int m, n;
    
    int max(int i, int j, int k, int l){
        int m = max(i, j), n = max(k, l);
        return max(m, n);
    }
    
    int main()
    {
        cin >> m >> n;
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++)
            {
                cin >> a[i][j];
            }
        }
        f[1][1][1][1] = 0; //garbage
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
                for(int k = i+1; k <= m; k++){
                    for(int l = 1; l < j; l++){
                        f[i][j][k][l] = max(
                            f[i][j-1][k][l-1],
                            f[i][j-1][k-1][l],
                            f[i-1][j][k-1][l],
                            f[i-1][j][k][l-1]
                        )+a[i][j]+a[k][l];
                    }
                }
            }
        }
        cout << f[m-1][n][m][n-1] << endl;
        return 0;    
    }
    
    • 0
      @ 2026-2-9 14:32:08
      #include<bits/stdc++.h>
      using namespace std;
      const int N=55;
      int f[N][N][N][N],a[N][N];
      int main()
      {
      	int n,m;cin>>n>>m;
      	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>a[i][j];
      	for(int i=1;i<=n;i++)
      	{
      		for(int j=1;j<=m;j++)
      		{
      			for(int x=1;x<=n;x++)
      			{
      				for(int y=1;y<=m;y++)
      				{
      					f[i][j][x][y]=max(max(f[i-1][j][x-1][y],f[i-1][j][x][y-1]),max(f[i][j-1][x-1][y],f[i][j-1][x][y-1]));
      					if(i!=x||j!=y)f[i][j][x][y]+=a[i][j]+a[x][y];
      					else f[i][j][x][y]+=a[i][j];
      					//f[i][j][x][y]为一个路径到(i,j),一个路径到(x,y)的最大值 
      				}
      			}
      		}
      	}
      	cout<<f[n][m][n][m];
      	return 0;
      }
      
      
    • 0
      @ 2025-10-8 16:52:01
      // 线性DP O(n^3)
      #include<bits/stdc++.h>
      using namespace std;
      
      const int N=55;
      int m,n,a[N][N];
      int f[N+N][N][N];
      
      int main(){
        cin>>m>>n;
        for(int i=1; i<=m; i++)
        for(int j=1; j<=n; j++) cin>>a[i][j];
        
        for(int k=2; k<=m+n; k++) //步数
        for(int i=1; i<=m; i++)   //行
        for(int x=1; x<=m; x++){  //行
          int j=k-i, y=k-x;
          if(j<1 || j>n || y<1 || y>n) continue;
          f[k][i][x]=max(max(f[k-1][i-1][x-1],f[k-1][i-1][x]), 
                         max(f[k-1][i][x-1], f[k-1][i][x]))+a[i][j]+a[x][y];
          if(i==x) f[k][i][x]-=a[i][j];
        }
        cout<<f[m+n][m][m];
      }
      
      #include <bits/stdc++.h>
      using namespace std;
      int f[51][51][51][51];//走一次就是f[n][m],两次就加两维,变成两次同时走 
      int a[51][51];
      int mymax(int x1, int x2, int x3, int x4)
      {
          return max(max(x1, x2), max(x3, x4));
      }
      int main()
      {
          int n, m;
          while(scanf("%d%d", &n, &m)!=EOF)
          {
              for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d", &a[i][j]);
              memset(f, 0, sizeof(f));
              for(int x1=1;x1<=n;x1++)
                  for(int y1=1;y1<=m;y1++)
                      for(int x2=1;x2<=n;x2++)
                          for(int y2=1;y2<=m;y2++)if(!(x1==x2&&y1==y2))
                          {
                              f[x1][y1][x2][y2]=mymax(f[x1-1][y1][x2-1][y2],
                                                      f[x1-1][y1][x2][y2-1],
                                                      f[x1][y1-1][x2-1][y2],
                                                      f[x1][y1-1][x2][y2-1])  +  a[x1][y1] 
                                                                              +  a[x2][y2];
                          }
              printf("%d\n", f[n][m-1][n-1][m]);//因为不能一个点在两个路径,所以f[n][m][n][m]无法被计算。 
          }
          return 0;
      }
      
      • 1

      信息

      ID
      726
      时间
      1000ms
      内存
      50MiB
      难度
      7
      标签
      递交数
      225
      已通过
      53
      上传者