题意
题解
每一行必须走完当前线段,再走到下一行,那么走完当前行时所在位置只有两种可能,即线段左端点与右端点。
d
p
[
i
]
[
0
]
,
d
p
[
i
]
[
1
]
dp[i][0],dp[i][1]
dp[i][0],dp[i][1] 分别代表在行
i
i
i 左右端点且走完当前行的线段时,在行方向的最短路程。
B
[
i
]
[
0
]
,
B
[
i
]
[
1
]
B[i][0],B[i][1]
B[i][0],B[i][1] 分别代表行
i
i
i 的左右端点。则有递推
d
p
[
i
]
[
j
]
=
min
k
∈
[
0
,
1
]
(
d
p
[
i
−
1
]
[
k
]
+
∣
B
[
i
−
1
]
[
k
]
−
B
[
i
]
[
j
⊕
1
]
∣
+
B
[
i
]
[
1
]
−
B
[
i
]
[
0
]
)
dp[i][j]=\min\limits_{k\in [0,1]}\left(dp[i-1][k]+\lvert B[i-1][k]-B[i][j\oplus 1]\rvert+B[i][1]-B[i][0]\right)
dp[i][j]=k∈[0,1]min(dp[i−1][k]+∣B[i−1][k]−B[i][j⊕1]∣+B[i][1]−B[i][0]) 列方向路径长度为常量
N
−
1
N-1
N−1,索引从
0
0
0 开始,则答案为
d
p
[
N
−
1
]
[
1
]
+
N
−
1
−
B
[
N
−
1
]
[
1
]
+
N
−
1
dp[N-1][1]+N-1-B[N-1][1]+N-1
dp[N−1][1]+N−1−B[N−1][1]+N−1
#include <bits/stdc++.h>
using namespace std;
const int maxn = 20005;
int N, B[maxn][2], dp[maxn][2];
int main()
{
cin >> N;
for (int i = 0; i < N; ++i)
cin >> B[i][0] >> B[i][1], --B[i][0], --B[i][1];
memset(dp, 0x3f, sizeof(dp));
dp[0][0] = B[0][1] * 2 - B[0][0], dp[0][1] = B[0][1];
for (int i = 1; i < N; ++i)
for (int j = 0; j < 2; ++j)
for (int k = 0; k < 2; ++k)
dp[i][j] = min(dp[i][j], dp[i - 1][k] + abs(B[i - 1][k] - B[i][j ^ 1]) + B[i][1] - B[i][0]);
cout << dp[N - 1][1] + N - 1 - B[N - 1][1] + N - 1 << endl;
return 0;
}