题目描述
在一个 n*n 的平面上,在每一行中有一条线段,第 i 行的线段的左端点是(i, L(i)),右端点是(i, R(i)),其中 1 ≤ L(i) ≤ R(i) ≤ n。
你从(1, 1)点出发,要求沿途走过所有的线段,最终到达(n, n)点,且所走的路程长度要尽量短。
更具体一些说,你在任何时候只能选择向下走一步(行数增加 1)、向左走一步(列数减少 1)或是向右走一步(列数增加 1)。当然,由于你不能向上行走,因此在从任何一行向下走到另一行的时候,你必须保证已经走完本行的那条线段。
输入格式
输入文件的第一行有一个整数 n,以下 n 行,在第 i 行(总第(i+1)行)的两个整数表示
L(i)和 R(i)。
输出格式
输出文件仅包含一个整数,你选择的最短路程的长度。 题目链接
状态表示:f[i][0] 表示走完前i行并且最终停到左端点的路程长度,f[i][1]表示停到右端点
状态计算:
f[i][0] = min(f[i-1][0] + dist(l[i-1],r[i]) + dist(r[i],l[i]) + 1, f[i-1][1] + dist(r[i-1],r[i]) + dist(r[i],l[i]) + 1)
;
f[i][1] = min(f[i-1][0] + dist(l[i-1],l[i]) + dist(l[i],r[i]) + 1, f[i-1][1] + dist(r[i-1],l[i]) + dist(l[i],r[i]) + 1)
;
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 20010;
int n;
int l[N],r[N];
int f[N][2];
int main()
{
cin >> n;
for(int i = 1;i <= n;i++) cin >> l[i] >> r[i];
f[1][0] = r[1] - 1 + r[1] - l[1];
f[1][1] = r[1] - 1;
for(int i = 2;i <= n;i++)
{
f[i][0] = min(f[i-1][0] + abs(l[i-1]-r[i]) + r[i] - l[i],
f[i-1][1] + abs(r[i-1]-r[i]) + r[i] - l[i]) + 1;
f[i][1] = min(f[i-1][0] + abs(l[i-1]-l[i]) + r[i] - l[i],
f[i-1][1] + abs(r[i-1]-l[i]) + r[i] - l[i]) + 1;
}
cout << min(f[n][0] + n - l[n],f[n][1] + n - r[n]) << endl;
return 0;
}