洛谷 P1006传纸条 ——四维DP,以及其对应的去重方法

四维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;
}

猜你喜欢

转载自blog.csdn.net/weixin_45502929/article/details/106773656