题目描述
设有 n × m n \times m n×m 的方格图,每个方格中都有一个整数。现有一只小熊,想从图的左上角走到右下角,每一步只能向上、向下或向右走一格,并且不能重复经过已经走过的方格,也不能走出边界。小熊会取走所有经过的方格中的整数,求它能取到的整数之和的最大值。
输入格式
第一行有两个整数 n , m n, m n,m。
接下来 n n n 行每行 m m m 个整数,依次代表每个方格中的整数。
输出格式
一个整数,表示小熊能取到的整数之和的最大值。
输入输出样例
输入 #1
3 4
1 -1 3 2
2 -1 4 -1
-2 2 -3 -1
输出 #1
9
输入 #2
2 5
-1 -1 -3 -2 -7
-2 -1 -4 -1 -2
输出 #2
-10
说明/提示
样例 1 解释
样例 2 解释
数据规模与约定
对于
20
%
20\%
20% 的数据,
n
,
m
≤
5
n, m \le 5
n,m≤5。
对于 40%40% 的数据,
n
,
m
≤
50
n, m \le 50
n,m≤50。
对于
70
%
70\%
70% 的数据,
n
,
m
≤
300
n, m \le 300
n,m≤300。
对于
100
%
100\%
100% 的数据,
1
≤
n
,
m
≤
1
0
3
1 \le n,m \le 10^3
1≤n,m≤103 。方格中整数的绝对值不超过
1
0
4
10^4
104 。
解题思路
先将方格转一下,即向左、向右、向下。
接着考虑
f
[
i
]
[
j
]
[
0
]
f[i][j][0]
f[i][j][0]表示左方向,
f
[
i
]
[
j
]
[
1
]
f[i][j][1]
f[i][j][1]表示右方向
- 向下走,那么上一行是左方向和右方向都可
if (i != 1)
{
f[i][j][0] = max (f[i][j][0], max (f[i - 1][j][0], f[i - 1][j][1]) + s[i][j]);
f[i][j][1] = max (f[i][j][1], max (f[i - 1][j][0], f[i - 1][j][1]) + s[i][j]);
}
- 向左走的话,在这一行都只能向左走
if (j != 1)
f[i][j][0] = max (f[i][j - 1][0] + s[i][j], f[i][j][0]);
- 向右走的话,在这一行都只能向右走
if (j != m)
f[i][j][1] = max (f[i][j + 1][1] + s[i][j], f[i][j][1]);
还有,记得开long long🙃
Code
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
long long n, m, s[1010][1010], f[1010][1010][2], t;
int main(){
scanf ("%lld%lld", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf ("%lld", &s[j][i]);
t = n, n = m, m = t;·
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
f[i][j][0] = f[i][j][1] = -1e18;
f[1][1][0] = f[1][1][1] = s[1][1];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (i != 1)
{
f[i][j][0] = max (f[i][j][0], max (f[i - 1][j][0], f[i - 1][j][1]) + s[i][j]);
f[i][j][1] = max (f[i][j][1], max (f[i - 1][j][0], f[i - 1][j][1]) + s[i][j]);
}
if (j != 1)
f[i][j][0] = max (f[i][j - 1][0] + s[i][j], f[i][j][0]);
}
for (int j = m - 1; j; j--)
f[i][j][1] = max (f[i][j + 1][1] + s[i][j], f[i][j][1]);
}
printf ("%lld", max(f[n][m][0], f[n][m][1]));
}