四维DP的典型模板题。
注意其中去重使用的思路。因为两条路不能有任何重复的节点,所以这两条路必然分立在整个地图当中,其中一者i
(行号)大,另一个j
(列号)大。所以对于第一条路,其横纵坐标的枚举是自由的,第二者有了一定的限制。
#include <bits/stdc++.h>
using namespace std;
int dp[52][52][52][52], a[52][52], n, m;
int max(int a, int s, int d, int f)//通过重载max函数,将使得我们的操作变得简明。
{
int z = max(a, s), x = max(d, f);
return max(z, x);
}
int main()
{
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 k = i+1; k <= n; k++){
for (int l = 1; l < j; l++){
dp[i][j][k][l]
= max(dp[i-1][j][k-1][l], //i-1和j-1分别对应着第一条路中节点向下(行变化),和节点向右(列变化)。
dp[i-1][j][k][l-1],
dp[i][j-1][k-1][l],
dp[i][j-1][k][l-1])
+ a[i][j] + a[k][l];
}
}
}
}
cout << dp[n-1][m][n][m-1];
}
三维同样是利用下标的大小关系。第三重循环是从i+1
开始的。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 60;
int a[maxn][maxn];
int F[2 * maxn][maxn][maxn];
int max(int a, int s, int d, int f)
{
int z = max(a, s), x = max(d, f);
return max(z, x);
}
int main()
{
int m, n;
scanf("%d%d", &m, &n);
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
scanf("%d", &a[i][j]);
for (int k = 3; k < m + n; k++)
for (int i = 1; i < k; i++)//小于k的枚举
for (int j = i + 1; j < k; j++)
F[k][i][j] = max(F[k - 1][i][j],F[k - 1][i - 1][j],F[k - 1][i][j - 1],F[k - 1][i - 1][j - 1]) + a[k - i][i] + a[k - j][j];
printf("%d", F[m + n - 1][n - 1][n]);
return 0;
}