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;
}

 

posted @ 2021-05-07 21:20  cminus  阅读(27)  评论(0编辑  收藏  举报