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

posted @ 2024-06-18 21:53  onlyblues  阅读(31)  评论(0)    收藏  举报
Web Analytics