cf*1800 Contest 2050 and Codeforces Round #718 (Div. 1 + Div. 2) D. Explorer Space
我到底是多菜才能这道题都做不出来啊
似乎是t神几分钟就写出来的题目
这道题的重点在于求长度为k的最短路,我的误区在于我一直想用各种最短路算法来解决,但是完全不需要
显然这种限制具体步数的问题可以用DP或者说是分层图来解决,当然从本质上来说分层图就是一种DP,考虑dp[k][i][j]表示从(i, j)出发走了k步的最短路(也可以看成是以(i, j)为终点用了k步的最短路,作为一个无向图,这两个是等价的),然后就可以直接dp求解了。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 510; int a[N][N][4]; ll dp[15][N][N]; int main() { int n, m, K; scanf("%d%d%d", &n, &m, &K); for (int i = 1; i <= n; i++) for (int j = 1; j < m; j++) { scanf("%d", &a[i][j][3]); a[i][j + 1][2] = a[i][j][3]; } for (int i = 1; i < n; i++) for (int j = 1; j <= m; j++) { scanf("%d", &a[i][j][0]); a[i + 1][j][1] = a[i][j][0]; } if (K % 2 == 1) { for (int i = 1; i <= n; i++, puts("")) for (int j = 1; j <= m; j++) printf("-1 "); return 0; } int move[4][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}}; memset(dp, 0x3f, sizeof(dp)); K = K / 2; for (int k = 1; k <= K; k++) for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { dp[0][i][j] = 0; for (int l = 0; l < 4; l++) { int x = i + move[l][0], y = j + move[l][1]; if (x < 1 || x > n || y < 1 || y > m) continue; dp[k][x][y] = min(dp[k][x][y], dp[k - 1][i][j] + a[i][j][l]); } } for (int i = 1; i <= n; i++, puts("")) for (int j = 1; j <= m; j++) printf("%lld ", dp[K][i][j] * 2); return 0; }