JSK习题:蒜头君的城堡之旅-dp

这里写图片描述

题意:

在一个二维矩阵上,给出一个起点和终点,矩阵上每个点的值代表价值,求从起点走到终点,再从终点返回起点,能取得的最大价值,且每个点只能走一次

思路:

对于来回路径上取值问题,很容易误以为先算从起点到终点能取得的最大价值,删去走过点后,再算一遍从终点到起点的最大价值
但显然这样只能保证去的时候得到了最大价值,而不能保证全局是最大的,所以不能这么做
将来回路径考虑成同时从起点出发到终点的两条路径,这两条路径的取值和最大,就是来回路能取的最大值
dp[i][j][k][l]表示从起点到(i,j)加上从起点到(k,l)能取得的最大价值
状态转移:dp[i][j][k][l]=max(max(max(dp[i-1][j][k-1][l],dp[i][j-1][k-1][l]),dp[i-1][j][k][l-1]),dp[i][j-1][k][l-1])+a[i][j]+a[k][l];

代码:

#include <iostream>
using namespace std;

const int maxn=55;
int dp[maxn][maxn][maxn][maxn];
int a[maxn][maxn];

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 k=1;k<=n;k++){
                for(int l=1;l<=m;l++)
                {
                    if(i+j != k+l) continue;
                    if(i==k && j==l) continue;
                    dp[i][j][k][l]=max(max(max(dp[i-1][j][k-1][l],dp[i][j-1][k-1][l]),dp[i-1][j][k][l-1]),dp[i][j-1][k][l-1])+a[i][j]+a[k][l];
                }
            }
        }
    }
    cout<<max(max(dp[n-1][m][n-1][m],dp[n-1][m][n][m-1]),max(dp[n][m-1][n][m-1],dp[n][m-1][n-1][m]))<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43093481/article/details/82588463