线段

题目链接:https://www.luogu.com.cn/problem/P3842

题意:

从上至下有n条线段,每条线段必须走完

求从( 1,1) - > (n,n) 最短路径长度

思路 :

可以认为每一行要把线段走完,那么一定会在其左右端点

因为多走不会使答案更优

记dp[i,0] ,dp[i,1] 分别为 走到 第 i个线段左端点/右端点的最短路径大小

两个都可以从dp[i-1,0] dp[i-1,1] 转移得到

注意初始化 a[0]=a[1]=1 (因为从1,1开始)

向下走的步数也要加上

#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define pb push_back
#define int long long
#define endl "\n"
#define fi first
#define se second
//#pragma GCC optimize(3)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 lll;
typedef pair<int,int> pii;
const int inf=0x3f3f3f3f;
const ll llmax=LLONG_MAX;
const int maxn=1e5+5;
const int mod=1e9+7;

void solve(){
	struct node{
		int l,r;
	};
	int pos;
	int n;cin>>n;
	vector<node>a(n+1);
	vector<array<int,2>>dp(n+1,{inf,inf});
	for(int i=1;i<=n;i++){
		int l,r;cin>>l>>r;
		a[i]={l,r};
	}
	a[0].l=a[0].r=1;
	dp[0][0]=0;
	dp[0][1]=0;
	for(int i=1;i<=n;i++){
		for(int k=0;k<=1;k++){
			if(k==0) pos=a[i-1].l;
			else  pos=a[i-1].r;
			if(pos<=a[i].l){
				dp[i][1]=min(dp[i][1],dp[i-1][k]+a[i].r-pos);
				dp[i][0]=min(dp[i][0],dp[i-1][k]+a[i].l-pos+2*(a[i].r-a[i].l));
			}
			else if(pos>=a[i].r){
				dp[i][0]=min(dp[i][0],dp[i-1][k]+pos-a[i].l);
				dp[i][1]=min(dp[i][1],dp[i-1][k]+pos-a[i].r+2*(a[i].r-a[i].l));
			}
			else{
				dp[i][0]=min(dp[i][0],dp[i-1][k]+a[i].r-pos+a[i].r-a[i].l);
				dp[i][1]=min(dp[i][1],dp[i-1][k]+pos-a[i].l+a[i].r-a[i].l);
			}
		}
	}
	int ans=inf;
	
	for(int k=0;k<=1;k++){
		if(k==0)pos=a[n].l;
		else pos=a[n].r;
		ans=min(ans,dp[n][k]+abs(n-pos));
	}
	
	cout<<ans+n-1<<endl;
}

signed main()
{
	ios::sync_with_stdio(false),cin.tie(0);
	int T=1;
	
	while(T--){
	solve();
	}
	
	return 0;
}


posted @ 2025-03-04 20:21  Marinaco  阅读(7)  评论(0)    收藏  举报
//雪花飘落效果