洛谷 P3842 [TJOI2007] 线段 题解

题目大意

原题链接

给你一个大小为 \(n \times n\)矩阵,上面有 \(n\) 条线段(一行一条)。你只能向右,向下,向左走。每一条线段都必须完整的经过。请问从 \((1,1)\)\((n,n)\) 最短路径长度是多少?

解法

这道题可以使用最短路或者DP来做。我觉得DP本题更简单一点所以我这里用的是DP。

可以设 \(dp_{i,0/1}\) 表示目前我已经看到第 \(i\) 行现在处于这条线段上的左边左端点还是右端点。(\(0\) 为左端点,\(1\) 为右端点)

于是我们就可以想到最初步的方法:每一次枚举从上一行的线段的左端点来还是右端点来,然后直接从选那个端点到当前的线段的左右个端点。即(以 \(dp_{i,0}\) 为例子):

\(dp_{i,0}=\min(dp_{i-1,0}+|l_{i-1}-l_{i}|,dp_{i-1,1}+|r_{i-1}-l_i|)+1\)

然后样例都没过,呜呜
就不放代码了

我们想想我们少了些什么?我们不能保证每一个线段到我们都完整的走过去。那我们应该怎么走呢?如下图:

image

沿着这个我们又可以得出新的DP方程(以 \(dp_{i,0}\) 为例):

\(dp_{i,0}=\min(dp_{i-1,0}+|l_{i-1}-r_i|+r_i-l_i+1,dp_{i-1,1}+abs(r_{i-1}-r_i)+r_i-l_i+1)\)

得到代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e4+5;
int l[maxn],r[maxn],dp[maxn][2];
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n;cin>>n;
	for(int i=1;i<=n;i++) cin>>l[i]>>r[i];
	dp[1][0]=r[1]+r[1]-l[1]-1,dp[1][1]=r[1]-1;//初始化
	for(int i=2;i<=n;i++)
	{
		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][1]+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;
	}
	cout<<min(dp[n][0],dp[n][1])+r[n]-l[n];//最后一次我们还没考虑
	return 0;
}

上洛古一交,得到:

image

14分

还少了点什么?原来我们的初始化和最后一次也不对。具体的可以见下图:

image

最后一次(答案):

image

于是修改一下初始化:

\(dp_{1,0}=r_1+r_1-l_1-1,dp_{1,1}=r_1-1\)

最后一行(答案):

\(\min(dp_{n,0}+n-l_n,dp_{n,1}+n-r_n)\)

真正的AC代码:终于完了

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e4+5;
int l[maxn],r[maxn],dp[maxn][2];
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n;cin>>n;
	for(int i=1;i<=n;i++) cin>>l[i]>>r[i];
	dp[1][0]=r[1]+r[1]-l[1]-1,dp[1][1]=r[1]-1;
	for(int i=2;i<=n;i++)
	{
		dp[i][0]=min(dp[i-1][0]+abs(l[i-1]-r[i])+r[i]-l[i]+1,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]+1,dp[i-1][1]+abs(r[i-1]-l[i])+r[i]-l[i]+1);
	}
	cout<<min(dp[n][0]+n-l[n],dp[n][1]+n-r[n]);
	return 0;
}

posted @ 2025-02-04 20:52  Engle_Chen  阅读(20)  评论(0编辑  收藏  举报