计蒜客蒜头君的城堡之旅

版权声明:原创博客 喜欢拿走 https://blog.csdn.net/qq_43004519/article/details/84451439

**

1.题目

**
蒜国地域是一个 n 行 m 列的矩阵,下标均从 1 开始。蒜国有个美丽的城堡,在坐标 (n,m) 上,蒜头君在坐标 (1,1) 的位置上。蒜头君打算出发去城堡游玩,游玩结束后返回到起点。在出发去城堡的路上,蒜头君只会选择往下或者往右走,而在返回的路上,蒜头君只会选择往上或者往左走,每次只能走一格。已知每个格子上都有一定数量的蒜味可乐,每个格子至多经过一次。
现在蒜头君请你来帮他计算一下,如何计划来回行程,可以收集到最多的蒜味可乐。
输入格式
第一行输入两个整数 n,m(1≤n,m≤50),表示蒜国是一个 n 行 m 列的矩阵。
接下来输入 n 行,每行输入 m 个整数,代表一个 n×m 的矩阵,每个整数代表对应位置上的蒜味可乐数量,每行的每两个整数之间用一个空格隔开。其中蒜头君的位置和城堡的位置上没有蒜味可乐,用 0 表示,其余位置上的整数范围在 [1,100] 内。
输出格式
输出一行,输出一个整数,表示蒜头君在来回路上能收集到的蒜味可乐的最大值。

2.分析

这道题虽说是一个人从起点走到终点,再从终点走回起点,要求两次走的路不可以相交,但可以看作两个人一起从起点走到终点,走的过程中不可以相遇,同时可以把两者位置合并到一个方程中,状态转移方程可表示为
dp[x1][y1][x2][y2]=max(max(dp[x1-1][y1][x2-1][y2],dp[x1][y1-1][x2][y2-1]),
max(dp[x1-1][y1][x2][y2-1],dp[x1][y1-1][x2-1][y2])) + num[x1][y1] + num[x2][y2];
1.可以假设为第一个人走到位置为(x1,y1),第二个人走的位置为(x2,y2)。
2.两者人不相遇即x1!=x2&&y1!=y2
3.看下面的代码,你可能会不明白x1+y1!=x2+y2的具体含义,如果两者是一起出发的话,那么x1+y1会等于x2+y2

3.AC代码

/*
dp[x1][y1][x2][y2]表示为(有两个人一起从(1,1)出发,且两人走的路不相交)第一个人走到(x1,y1),第二个人走到(x2,y2)
时收集到的可乐总数,
*/
#include<iostream>
using namespace std;

int main()
{
    int num[51][51];//记录可乐数量
    int dp[51][51][51][51];
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
            cin>>num[i][j];
    }
    dp[1][1][1][1]=num[1][1];//初始化状态
    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)//走到同一点
                        continue;
                    if(x1+y1!=x2+y2)//两者不是同时出发
                        continue;
                    //两个人,四种状态,取其最大值
                    dp[x1][y1][x2][y2]=max(max(dp[x1-1][y1][x2-1][y2],dp[x1][y1-1][x2][y2-1]),
                                           max(dp[x1-1][y1][x2][y2-1],dp[x1][y1-1][x2-1][y2]))+num[x1][y1]+num[x2][y2];
                }
            }
        }
    }
    cout<<dp[n-1][m][n][m-1]<<endl;
    return 0;//give me five
}

猜你喜欢

转载自blog.csdn.net/qq_43004519/article/details/84451439
今日推荐