CF_2193_F. Pizza Delivery(DP)
题目链接:Problem - 2193F - Codeforces
题目大意:
从起点(Ax, Ay)出发,每次可向右、向左或向下移动一格,需依次经过n个给定点(横坐标严格介于Ax与Bx之间),
最后到达终点(Bx, By)。每移动一格耗时1秒,求最短总时间。
思路:
由于开始写题时理解有些偏差,这里的x轴是纵轴,y是横轴
首先,对于x轴,走的路程是固定的,因为不能往上走
然后,对于y轴,对于相同的x坐标,最后要往下走时只能是位于当前x轴的最左边或最右边,因为不能从左走到右再回到中间的位置往下走,反之亦然
再记录相同x轴上的最左端点的位置与最右端点的位置,
我们用f[x][0]表示位于x轴上最左端时的最短时间,f[x][1]表示位于x轴上最右端时的最短时间
最后求出min(f[lst][0],f[lst][1])就是y轴上一共走过的距离
答案就是y轴上走的距离+x轴上走过的距离(固定=bx-ax)

橙色部分为走过的距离
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<map>
#include<bitset>
#include<tuple>
#include<array>
#define inf 72340172838076673
#define int long long
#define endl '\n'
#define F first
#define S second
#define mst(a,x) memset(a,x,sizeof (a))
using namespace std;
typedef pair<int, int> pii;
const int N = 200086, mod = 998244353;
int n, ax, ay, bx, by;
pii e[N];
int f[N][2];
void solve() {
cin >> n >> ax >> ay >> bx >> by;
vector<array<int, 2>> t(n + 2);
for (int i = 1; i <= n; i++) cin >> e[i].F;
for (int i = 1; i <= n; i++) {
cin >> e[i].S;
t[i][0] = inf, t[i][1] = -inf;
}
e[0] = {ax, by};
e[n + 1] = {bx, by};
t[n + 1] = {inf, -inf};
n++;
sort(e, e + n + 1);
int idx = 0;
for (int i = 1; i <= n; i++) {
auto [x, y] = e[i];
if (e[i - 1].F != x) idx++;
t[idx][0] = min(t[idx][0], y);
t[idx][1] = max(t[idx][1], y);
}
t[0][0] = t[0][1] = ay;
for (int i = 1; i <= idx; i++) {
f[i][0] = min(f[i - 1][0] + abs(t[i - 1][0] - t[i][1]) + (t[i][1] - t[i][0]),
f[i - 1][1] + abs(t[i - 1][1] - t[i][1]) + (t[i][1] - t[i][0]));
f[i][1] = min(f[i - 1][0] + abs(t[i - 1][0] - t[i][0]) + (t[i][1] - t[i][0]),
f[i - 1][1] + abs(t[i - 1][1] - t[i][0]) + (t[i][1] - t[i][0]));
}
cout << min(f[idx][0], f[idx][1]) + bx - ax << endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
cin >> T;
while (T--) solve();
return 0;
}

浙公网安备 33010602011771号