G - AtCoder Tour
G - AtCoder Tour
Problem Statement
AtCoder Land is represented by a grid with rows and columns. Let denote the cell at the -th row and -th column.
Takahashi starts at cell and repeats the following action times:
- He either stays in the current cell or moves to an adjacent cell. After this action, if he is in cell , he gains a fun value of .
Find the maximum total fun value he can gain.
Here, a cell is considered adjacent to cell if and only if .
Constraints
- All input values are integers.
Input
The input is given from Standard Input in the following format:
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 by acting as follows:
- Initially, he is at .
- He moves to cell . Then, he gains a fun value of .
- He moves to cell . Then, he gains a fun value of .
- He stays in cell . Then, he gains a fun value of .
He cannot gain a total fun value greater than , so print .
Sample Input 2
2 2 1000000000
2 1
100 100
100 99
Sample Output 2
100000000000
解题思路
对于任意一条以 为起点的路径,假设 是路径中经过的权值最大的格子,那么在路径中第一次经过 之后的格子是完全没必要访问的,因为 处的权值大于或等于之后要访问的格子,因此停留在 处所获得的收益更大。同时在 的过程中,除了 外,每个格子最多会被访问一次,否则路径中会存在一个环,容易知道把环去掉以更多的停留在 所能获得的收益更大。因此在最优解中,最后必然是停留在某个格子上,且从 到该格子路径上每个格子最多被访问一次。
为此,我们可以按最后停留的格子对所有情况进行分类。当确定最后停留的格子是 后,如何确定 到 的路径?一个错误的贪心思路是走一条长度为 的权值最大的路径,然后剩下的步数都停留在 。可以参考下面的样例发现错误:
2 4 5
1 1
1 1 1 100
99 99 99 99
错误的贪心思路结果为 ,而最优解是 。
显然我们可以多走几格,又因为从 到 的过程中每个格子最多被访问一次,因此最多会走 个格子。定义 表示以 为起点,无重复经过 个格子到达 的所有方案中权值和的最大值。状态转移方程就是 。
最后答案就是 。
AC 代码如下,时间复杂度为 :
#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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效