G - AtCoder Tour
G - AtCoder Tour
Problem Statement
AtCoder Land is represented by a grid with $H$ rows and $W$ columns. Let $(i, j)$ denote the cell at the $i$-th row and $j$-th column.
Takahashi starts at cell $(S_i, S_j)$ and repeats the following action $K$ times:
- He either stays in the current cell or moves to an adjacent cell. After this action, if he is in cell $(i, j)$, he gains a fun value of $A_{i, j}$.
Find the maximum total fun value he can gain.
Here, a cell $(x', y')$ is considered adjacent to cell $(x, y)$ if and only if $|x - x'| + |y - y'| = 1$.
Constraints
- $1 \leq H, W \leq 50$
- $1 \leq K \leq 10^9$
- $1 \leq S_i \leq H$
- $1 \leq S_j \leq W$
- $1 \leq A_{i, j} \leq 10^9$
- All input values are integers.
Input
The input is given from Standard Input in the following format:
$H$ $W$ $K$
$S_i$ $S_j$
$A_{1, 1}$ $A_{1, 2}$ $\ldots$ $A_{1, W}$
$A_{2, 1}$ $A_{2, 2}$ $\ldots$ $A_{2, W}$
$\vdots$
$A_{H, 1}$ $A_{H, 2}$ $\ldots$ $A_{H, W}$
Output
Print the answer.
Sample Input 1
2 3 3
1 2
2 1 2
3 4 5
Sample Output 1
14
Takahashi can gain a total fun value of $14$ by acting as follows:
- Initially, he is at $(1, 2)$.
- He moves to cell $(2, 2)$. Then, he gains a fun value of $A_{2, 2} = 4$.
- He moves to cell $(2, 3)$. Then, he gains a fun value of $A_{2, 3} = 5$.
- He stays in cell $(2, 3)$. Then, he gains a fun value of $A_{2, 3} = 5$.
He cannot gain a total fun value greater than $14$, so print $14$.
Sample Input 2
2 2 1000000000
2 1
100 100
100 99
Sample Output 2
100000000000
解题思路
对于任意一条以 $(s_x, s_y)$ 为起点的路径,假设 $(t_x, t_y)$ 是路径中经过的权值最大的格子,那么在路径中第一次经过 $(t_x, t_y)$ 之后的格子是完全没必要访问的,因为 $(t_x, t_y)$ 处的权值大于或等于之后要访问的格子,因此停留在 $(t_x, t_y)$ 处所获得的收益更大。同时在 $(s_x, s_y) \to (t_x, t_y)$ 的过程中,除了 $(t_x, t_y)$ 外,每个格子最多会被访问一次,否则路径中会存在一个环,容易知道把环去掉以更多的停留在 $(t_x, t_y)$ 所能获得的收益更大。因此在最优解中,最后必然是停留在某个格子上,且从 $(s_x, s_y)$ 到该格子路径上每个格子最多被访问一次。
为此,我们可以按最后停留的格子对所有情况进行分类。当确定最后停留的格子是 $(i, j)$ 后,如何确定 $(s_x, s_y)$ 到 $(i, j)$ 的路径?一个错误的贪心思路是走一条长度为 $|s_x - i| + |s_y - j|$ 的权值最大的路径,然后剩下的步数都停留在 $(i, j)$。可以参考下面的样例发现错误:
2 4 5
1 1
1 1 1 100
99 99 99 99
错误的贪心思路结果为 $1 + 1 + 100 + 100 + 100$,而最优解是 $99 + 99 + 99 + 99 + 100$。
显然我们可以多走几格,又因为从 $(s_x, s_y)$ 到 $(i,j)$ 的过程中每个格子最多被访问一次,因此最多会走 $n \cdot m$ 个格子。定义 $f(u,i,j)$ 表示以 $(s_x, s_y)$ 为起点,无重复经过 $u$ 个格子到达 $(i,j)$ 的所有方案中权值和的最大值。状态转移方程就是 $f(u,i,j) = \max\limits_{|i-x|+|j-y|=1}\left\{ f(u-1,x,y) + w_{i,j} \right\}$。
最后答案就是 $\max\limits_{u,i,j}\left\{f(u,i,j) + (k-u) \cdot w_{i,j}\right\}$。
AC 代码如下,时间复杂度为 $O\left(n^2 m^2\right)$:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 55;
int g[N][N];
LL f[N * N][N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int main() {
int n, m, k, x, y;
scanf("%d %d %d %d %d", &n, &m, &k, &x, &y);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%d", &g[i][j]);
}
}
memset(f, -0x3f, sizeof(f));
f[0][x][y] = 0;
for (int u = 1; u < n * m && u <= k; u++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
for (int k = 0; k < 4; k++) {
int x = i + dx[k], y = j + dy[k];
if (i <= 0 || i > n || j <= 0 || j > m) continue;
f[u][i][j] = max(f[u][i][j], f[u - 1][x][y] + g[i][j]);
}
}
}
}
LL ret = 0;
for (int u = 0; u < n * m && u <= k; u++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
ret = max(ret, f[u][i][j] + LL(k - u) * g[i][j]);
}
}
}
printf("%lld", ret);
return 0;
}
参考资料
Editorial - AtCoder Beginner Contest 358:https://atcoder.jp/contests/abc358/editorial/10226
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18255237