Vijos-p1143 three-take square number (dynamic programming multi-process dp)

background

Jerry Zhou often adapts exercises for himself.

On this day, he adapted another question. . . . .

description

There is an N*N grid graph, we fill some of the squares with a positive integer,
and other squares with 0.

Starting from the upper left corner of the picture, someone can go down or to the right until they reach the lower right corner.

On the way he walked, he took the number from the square. (The number in the square becomes 0 after taking it away.)
This person walks 3 times from the upper left corner to the lower right corner, try to find 3 paths to maximize the sum of the obtained numbers.

format

Input format

The first row: N (4<=N<=20) The
next N*N matrix, each element in the matrix does not exceed 80 and not less than 0

Output format

One line represents the largest sum.

Example 1

Sample input 1

4
1 2 3 4
2 1 3 4
1 2 3 4
1 3 2 4

Sample output 1

39

limit

1s for each test point

prompt

Multi-process DP

Problem solving

Portal

// dp[x][i][j][k] 表示第k步三条路径分别在i, j, k行时的最大收益
// 由于只有向右或向下走所以步数减去行数 + 1就是列数
// 3条路径那每步就有8种选择, 计算出最大收益步.
// 求解问题前分析有哪些变量之间有哪些变换关系, 以及变量的相关性
// 从枚举的思路先出发, 进一步发现规律, 得出更优算法

Code

#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 22;
int a[maxn][maxn];
int dp[2 * maxn][maxn][maxn][maxn];

int N, ans;
int main() {
    
    
    cin >> N;
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= N; j++) cin >> a[i][j];

    for (int x = 1; x <= 2 * N - 1; x++) {
    
    
        for (int i = 1; i <= N; i++) {
    
    
            for (int j = 1; j <= N; j++) {
    
    
                for (int k = 1; k <= N; k++) {
    
    
                    // 分别为
                    int il = x - i + 1, jl = x - j + 1, kl = x - k + 1;
                    if (il < 0 || jl < 0 || kl < 0) continue;
                    dp[x][i][j][k] =
                        max({
    
    dp[x - 1][i - 1][j][k],      // i向下, j, k向右
                             dp[x - 1][i][j - 1][k],      // i, k向右, j向下
                             dp[x - 1][i][j][k - 1],      // i, j向右, k向下
                             dp[x - 1][i - 1][j - 1][k],  // i, j向下, k向右
                             dp[x - 1][i - 1][j][k - 1],  // i, k向下, j向右
                             dp[x - 1][i][j - 1][k - 1],  // i 向右, j, k向下
                             dp[x - 1][i - 1][j - 1][k - 1],  // i, j, k向下
                             dp[x - 1][i][j][k]});            // i,j,k向右
                    //先加上三步的值, 下面再删除重复的值
                    dp[x][i][j][k] += a[i][il] + a[j][jl] + a[k][kl];
                    if (i == j) dp[x][i][j][k] -= a[i][il];
                    if (j == k) dp[x][i][j][k] -= a[j][jl];
                    if (i == k) dp[x][i][j][k] -= a[k][kl];
                    if (i == j && j == k) dp[x][i][j][k] += a[i][il];
                }
            }
        }
    }

    cout << dp[2 * N - 1][N][N][N] << endl;

    system("pause");
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_45349225/article/details/109553584