题目大意

n×nn \times n 的格上,在每行中各有一条线段 (i,li)(i,ri)(i, l_i) \to (i, r_i)

你从 (1,1)(1,1) 出发,只能沿着格子直走,最终走到 (n,n)(n,n)。要求沿途经过所有的线段,且所走路程长度尽量的短。

分析

显然是一行一行的递推。维护两个数据,一个是走完该行后停留在左侧的,记作 DPl{\rm DP}_l,相应的停留在右侧的记作 DPr{\rm DP}_r

若停在左侧,可能从上一行的右侧走来,也可能是由左侧走来,故转移方程有

DPl[i]=rili+min{DPl[i1]+li1ri,DPr[i1]+ri1ri} {\rm DP}_l[i] = r_i - l_i + \min\{{\rm DP}_l[i - 1] + |l_{i-1} - r_i|, {\rm DP}_r[i - 1] + |r_{i - 1} - r_i|\}

右侧类似,故可以写出代码

int main() {
	int n = rr();
	ll past_l = 1, past_r = 1, dpl = 0, dpr = 0;
	for (ll i = 1; i <= n; i++) {
		ll l = rr(), r = rr();
		ll tl = min(dpl + abs(past_l - r), dpr + abs(past_r - r)) + r - l;
		ll tr = min(dpl + abs(past_l - l), dpr + abs(past_r - l)) + r - l;
		dpl = tl, dpr = tr;
		past_l = l, past_r = r;
	}
	printf("%lld\n", min(dpl + n - past_l, dpr + n - past_r) + n - 1);
	return 0;
}