3 条题解
-
0
感觉应该对2条路径走到一个点(重复点)处理方法不懂
举例一个四维dp的里的做法(三维等解法的大佬不要嘲笑)首先,起点到终点走两次与题意是等效的。
四位dp很容易想,但对于大佬题解里重复点的处理,蒟蒻实在是有点不太明白我们可以这样想,2条路径不相交,那么肯定一条在上面,一条在下面,如图是随便画的2条路径

是红色路径的坐标,是黑色路径的坐标
那么对于,我们只需枚举,只需枚举即可
这样就不用判重啦由于最后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
#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
// 线性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
- 上传者