【洛谷 P3842 [TJOI2007]线段】解题报告(动态规划)

题面

在一个 n×n 的平面上,在每一行中有一条线段,第 i 行的线段的左端点是 (i,Li),右端点是 (i,Ri)

你从 (1,1) 点出发,要求沿途走过所有的线段,最终到达 (n,n) 点,且所走的路程长度要尽量短。

更具体一些说,你在任何时候只能选择向下走一步(行数增加 1)、向左走一步(列数减少 1)或是向右走一步(列数增加 1)。当然,由于你不能向上行走,因此在从任何一行向下走到另一行的时候,你必须保证已经走完本行的那条线段。

1n2×1041LiRin

题解

本题的状态比较显然。

由于每一层必然走过整条线段,所以显然从线段的左/右端点向下走是最优的。我们拆分子问题,求从 (1,1) 走到第 i 层线段左/右端点的最少步数,可以通过从 (1,1) 走到第 i1 层线段左/右端点的最少步数求出,因此从 (1,1) 走到第 i 层线段左/右端点的最少步数就是一个子问题。

根据我们得到的子问题,我们设状态 dpi,[0/1] 表示从 (1,1) 走到第 i 层线段的左/右端点的最少步数。以从 dpi1,0dpi,1 转移为例(也就是从上一层线段左端点走到这一层线段右端点),我们首先需要横向走到这一层线段左端点,将横坐标从 Li1 走到 Li,显然需要 |Li1Li| 步,然后从线段左端点走到线段右端点,显然需要 RiLi 步,又因为需要从上一层走到这一层,还需要额外的 1 步。我们得到转移 dpi,1dpi1,0+|Li1Li|+RiLi+1。类似地,我们可以得到从 dpi1,[0/1]dpi,[0/1] 的所有转移,对于一个目标状态,把所有能转移过来的结果取最小值即可。

最终我们还需要从 LnRn 走到 (n,n),可以按照类似的方法求出 ansmin{dpn,0+nLn,dpn,1+nRn}

初始状态就是从 (1,1)R1 的距离,或者到 R1 再到 L1 的距离。

参考代码

//By: Luogu@rui_er(122461)
#include <bits/stdc++.h>
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
#define debug printf("Running %s on line %d...\n",__FUNCTION__,__LINE__)
using namespace std;
typedef long long ll;
const int N = 2e4+5; 

int n, L[N], R[N], dp[N][2];
template<typename T> void chkmin(T &x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T &x, T y) {if(x < y) x = y;}

int main() {
    scanf("%d", &n);
    rep(i, 1, n) scanf("%d%d", &L[i], &R[i]);
    dp[1][0] = 2 * R[1] - L[1] - 1;
    dp[1][1] = R[1] - 1;
    rep(i, 2, n) {
        dp[i][0] = min(dp[i-1][0]+abs(L[i-1]-R[i])+R[i]-L[i], 
                       dp[i-1][1]+abs(R[i-1]-R[i])+R[i]-L[i]) + 1;
        dp[i][1] = min(dp[i-1][0]+abs(L[i-1]-L[i])+R[i]-L[i], 
                       dp[i-1][1]+abs(R[i-1]-L[i])+R[i]-L[i]) + 1;
    }
    int ans = min(dp[n][0]+n-L[n], dp[n][1]+n-R[n]);
    printf("%d\n", ans);
    return 0;
}
posted @   rui_er  阅读(90)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示