Contest 2050 and Codeforces Round #718 游记
次阅读
4 min read
难得有一场比赛大家全都来打了!
然而却是越做越糊涂,D 题开始搞错 后来又分析错时间,最后绝望极了,没能坚持到最后,放弃治疗。第二天发现其实挺简单的。
A
简单题。一遍过。
B
血的教训!清空不能一直滥用 memset
, 不然这种多测保证积的和不超过几几几的会 T 掉。
C
简单题。一遍过。
D
给定一张网格图,求每个点走 次后恰好回来所经过的最小边权。
恰好回来的这种问题一看就想到分层图,然后一算时间是 , 看到 才二十以为能过,就无脑写了一波分层图 Dijkstra, 然后一开始搞错了 和 , Wrong Answer on pretest 4, 修改后又 T 在了 pretest 5, 还傻乎乎的以为是小问题,然后交了两次 T 才自己造数据。
还瞎搞了一些无关紧要的压低常数做法,结果到好久之后才发现有 张图,时间应该是 的,根本就是渐进复杂度错了。然后就绝望等死了没去重新想正解,转而放弃治疗了。
其实正解还要简单。
有一个很显然的性质,那就是一定是跑 步后原路返回的,反证法易证。那么只需要看一个走 步最少跨越多少边权了,随便 dp 或者记忆化搜索都可以。
最后还发现,原来先前写的代码不仅 搞错,循环的顺序也反了……
代码。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
const int N = 505, K = 25, INF = 0x3f3f3f3f3f3f3f3fll, D = 1, U = 2, L = 3, R = 4;
int n, m, k, f[N][N][K], to[5][N][N], ans[N][N];
int dx[5] = {0, 1, -1, 0, 0},
dy[5] = {0, 0, 0, -1, 1};
int dfs(int x, int y, int k) {
if(k == 0) return 0;
if(f[x][y][k] != -1) return f[x][y][k];
f[x][y][k] = INF;
for(int i = 1; i <= 4; i++) {
int xx = x + dx[i], yy = y + dy[i];
if(xx < 1 || xx > n || yy < 1 || yy > m) continue;
f[x][y][k] = std::min(f[x][y][k], dfs(xx, yy, k-1) + to[i][x][y]);
}
return f[x][y][k];
}
signed main() {
scanf("%lld%lld%lld", &n, &m, &k);
for(int i = 1; i <= n; i++)
for(int j = 1; j < m; j++) scanf("%lld", &to[R][i][j]), to[L][i][j+1] = to[R][i][j];
for(int i = 1; i < n; i++)
for(int j = 1; j <= m; j++) scanf("%lld", &to[D][i][j]), to[U][i+1][j] = to[D][i][j];
memset(f, -1, sizeof f);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
dfs(i, j, k/2);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) printf("%lld ", (k & 1) ? -1 : f[i][j][k/2]*2);
puts("");
}
return 0;
}
虽说比赛打得不怎么样,但别灰心啊,继续加油,总会有突破的。