Codeforces Round 994 (Div. 2)-D题

题目链接:https://codeforces.com/contest/2049/problem/D

题目大意是在开始移动之前,可以任意次将一行元素向左挪一格,代价是1,开始游戏后,只能向下走或者向右走,直到走到终点,问最小代价是多少.

cpp 复制代码
constexpr ll inf = 1E18;
void solve() {
    int n, m, K;
    std::cin >> n >> m >> K;
    std::vector<std::vector<int>>a(n, std::vector<int>(m));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            std::cin >> a[i][j];
        }
    }
    std::vector<ll>dp(m, inf);
    dp[0] = 0;
    for (int i = 0; i < n; i++) {
        std::vector<ll>ndp(m, inf);
        for (int j = 0; j < m; j++) {
            auto g = dp;
            for (int k = 0; k < m; k++) {
                if (k) {
                    g[k] = std::min(g[k], g[k - 1]);
                }
                g[k] += a[i][(j + k) % m];
                ndp[k] = std::min(ndp[k], g[k] + 1LL * j * K);
            }
        }
        dp = std::move(ndp);
    }
    std::cout << dp[m - 1] << "\n";
}

dpk表示走到第i列的最小代价,枚举每一行i,此时dpk表示走到(i-1,k)的最小代价,现在我们想要求走到(i,k)的最小代价,我们知道它可以由(i,k-1)和(i-1,k)转移过来,在k=0的时候(i,k-1)不存在,我们直接跳过,那么它的状态只能是从(i-1,k)转移过来,也就是dpk表示的值,由于我们要多次修改dp的值,所以每一次都要复制一份新的dp,用g来表示,j表示我们在开始的时候让第i行向左偏移了多少次,那么此时第(i,k)位置的元素变成了ai(j+k)%m,为了方便理解不妨把省略的行号列出来,此时g0表示的其实是gi-10,我们枚举的偏移量,那么如果它向下走,加上一个ai(j+k)%m变成了gi0,然后,我们再来计算g1,此时g1表示的是gi-11,注意此时g0表示的是gi0,那么gi1可以由

min(gi-11+a,gi0+a)转移而来,所以代码中gk=min(gk,gk-1)的操作其实是计算

gi-1k,gik-1的最小值,然后加上一个a,ndp表示在尝试所有偏移量j以后计算而来的第i的最小值,然后还给dp,然后不断重复这一部分操作即可.

相关推荐
choumou_M1 分钟前
算法_1:由浅入深学习快速排序QuickSort
学习·算法·排序算法
Coder_Shenshen34 分钟前
罗克韦尔ACD工程归档离线变量树解析
算法·c#
心仪久了会沦陷2 小时前
C语言数据结构入门——树与二叉树详解:概念、堆实现与链式遍历
c语言·数据结构·算法
小此方2 小时前
[算法实战论:动态规划]背包问题概念,01不满背包问题,01满背包问题,背包问题的滚动数组空间优化
算法·动态规划
悠仁さん3 小时前
【C++】哈希表
c++·算法·散列表
地平线开发者4 小时前
点云算法整理与常用计算模块:从数据到模型,再到工程与量化
算法·自动驾驶
武子康6 小时前
H3-World 为何在加载 LoRA 前,先检查导入的代码?
人工智能·深度学习·算法
秋天的怀念_David7 小时前
算法一千零一夜 · 第二十八夜 注册
java·程序人生·算法
NEFU_Jyj9 小时前
贝尔数(组合数学)
算法
希和202710 小时前
C语言程序设计题|有序数组插入数字冒泡排序
c语言·数据结构·算法