蒜头君的城堡之旅(dp)
作者:互联网
题目:
蒜国地域是一个 n 行 m 列的矩阵,下标均从 1 开始。蒜国有个美丽的城堡,在坐标 (n,m) 上,蒜头君在坐标 (1,1) 的位置上。蒜头君打算出发去城堡游玩,游玩结束后返回到起点。在出发去城堡的路上,蒜头君只会选择往下或者往右走,而在返回的路上,蒜头君只会选择往上或者往左走,每次只能走一格。已知每个格子上都有一定数量的蒜味可乐,每个格子至多经过一次。现在蒜头君请你来帮他计算一下,如何计划来回行程,可以收集到最多的蒜味可乐。
输入格式
第一行输入两个整数 n,m(1≤n,m≤50),表示蒜国是一个 n 行 m 列的矩阵。接下来输入 n 行,每行输入 m 个整数,代表一个 n×m 的矩阵,每个整数代表对应位置上的蒜味可乐数量,每行的每两个整数之间用一个空格隔开。其中蒜头君的位置和城堡的位置上没有蒜味可乐,用 0 表示,其余位置上的整数范围在 [1,100] 内。
输出格式
输出一行,输出一个整数,表示蒜头君在来回路上能收集到的蒜味可乐的最大值。
样例输入
3 3
0 2 9
4 8 6
2 7 0
样例输出
36
tap
#include <iostream>
using namespace std;
int map[60][60] = {0}, dp[60][60][60][60] = {0}; //真~四重存在~(其实就是储存了两个点坐标)
int main()
{
int n, m, x1, x2, y1, y2;
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> map[i][j]; //蒜头可乐地图
for (x1 = 1; x1 <= n; x1++)
{
for (y1 = 1; y1 <= m; y1++)
for (x2 = 1; x2 <= n; x2++)
{
y2 = x1 + y1 - x2; //降低复杂度的玩意儿,避免出现四重循环判断
if (y2 > m || y2 < 1) //越界,退散
continue;
if (x1 != x2 && y1 != y2) //两人能在同一点
{
dp[x1][y1][x2][y2] = max(
max(dp[x1 - 1][y1][x2 - 1][y2], dp[x1][y1 - 1][x2][y2 - 1]),
max(dp[x1][y1 - 1][x2 - 1][y2], dp[x1 - 1][y1][x2][y2 - 1])) +map[x1][y1] + map[x2][y2];
} }}//来自上个状态的可乐数(注意每个人都是上一次状态,故每个坐标都有上个状态的调用,故有四个旧态)
int a;
a = max(max(dp[n - 1][m][n - 1][m], dp[n - 1][m][n][m - 1]),//到达终点时可能通过终点左边到达,也可能是从终点上方到达
max(dp[n][m - 1][n - 1][m], dp[n][m - 1][n][m - 1]));
cout << a;
return 0;
}
/*先整理一下思路:蒜头往返两次,两次的终点起点相反,且一个格子不能走两次,一个人的往返过程可以等效为两个人都从起点出发,到达同一个终点
并且两人走的格子不能相同,并且两人同步前进(步数也相同),求两人到达终点时取得的最大可乐数(要综合考虑,如果单算单程,不能保证全过程最优)*/
给我搞楞了
标签:蒜头,x1,之旅,x2,y1,y2,dp 来源: https://www.cnblogs.com/emokable/p/16086762.html