傳送門
亂搞。
能夠發現若是起點在左邊界,終點在右邊界的時候上下走的點必定是連續的(可能吧)
那麼能夠設 \(f_{i,j,0/1}\) 表示當前上面到 \(i\),下面到 \(j\),當前在上面/下面的最短距離。
若是起點不在左邊界,終點不在右邊界,那麼就亂搞。
對於左邊,若是向左的時候下去了再上來必定不會優與直接走過去,那麼就分兩種狀況:左下右 或者 直接先左再次原路返回向右。
右邊相似,每次到一個點用這個策略更新一下答案。
以後交換左右再作一遍便可不想卡常了,BZOJ直接特判了QwQ
上述(假算法)策略成功水過了全部的測試點。c++
# include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn(10005); int n, m, a, b, c, d, id[maxn]; double x1[maxn], x2[maxn], h, tmp[maxn], f[2][maxn][2], ans, inf, sqr1, sqr2; inline double Dis(double x, double y) { return sqrt((x - y) * (x - y) + h * h); } inline double Calcans(int p1, int p2, int op) { if (c == 1) { if (op) { if (p1 == d) return x2[m] - x2[p2] + sqr2 + x1[n] - x1[d]; return x2[m] - x2[p2] + sqr2 + x1[n] - x1[p1 + 1] + x1[d] - x1[p1 + 1]; } if (p2 == m) return x1[n] - x1[p1] + x1[n] - x1[d]; return x1[d - 1] - x1[p1] + Dis(x1[d - 1], x2[p2 + 1]) + x2[m] - x2[p2 + 1] + sqr2 + x1[n] - x1[d]; } else { if (!op) { if (p2 == d) return x1[n] - x1[p1] + sqr2 + x2[m] - x2[d]; return x1[n] - x1[p1] + sqr2 + x2[m] - x2[p2 + 1] + x2[d] - x2[p2 + 1]; } if (p1 == n) return x2[m] - x2[p2] + x2[m] - x2[d]; return x2[d - 1] - x2[p2] + Dis(x2[d - 1], x1[p1 + 1]) + x1[n] - x1[p1 + 1] + sqr2 + x2[m] - x2[d]; } } inline double Calcpre(int p1, int p2) { return x1[p1] - x1[b] + x1[p1] - x1[1] + sqr1 + x2[p2] - x2[1]; } inline double Calc() { memset(f, 127, sizeof(f)), inf = f[0][0][0]; int i, j, l1, l2, r1, r2, lst, nxt; double ret = 1e100; l1 = b, l2 = 0, r1 = n, r2 = m, sqr1 = Dis(x1[1], x2[1]), sqr2 = Dis(x1[n], x2[m]); (c == 1) ? r1 = d : r2 = d; lst = 0, nxt = 1; for (i = l1; i <= r1; ++i) { f[lst][1][1] = min(f[lst][1][1], Calcpre(i, 1)); f[lst][0][0] = min(f[lst][1][0], x1[i] - x1[1] + x1[b] - x1[1]); for (j = l2; j <= r2; ++j) if (f[lst][j][0] < inf || f[lst][j][1] < inf) { if (i && j) { f[lst][j][1] = min(f[lst][j][1], f[lst][j][0] + Dis(x1[i], x2[j])); f[lst][j][0] = min(f[lst][j][0], f[lst][j][1] + Dis(x1[i], x2[j])); ret = min(ret, f[lst][j][0] + Calcans(i, j, 0)); ret = min(ret, f[lst][j][1] + Calcans(i, j, 1)); } if (i && j < r2) f[lst][j + 1][1] = min(f[lst][j + 1][1], f[lst][j][0] + Dis(x1[i], x2[j + 1])); if (j && i < r1) f[nxt][j][0] = min(f[nxt][j][0], f[lst][j][1] + Dis(x2[j], x1[i + 1])); if (j && j < r2) f[lst][j + 1][1] = min(f[lst][j + 1][1], f[lst][j][1] + x2[j + 1] - x2[j]); if (i && i < r1) f[nxt][j][0] = min(f[nxt][j][0], f[lst][j][0] + x1[i + 1] - x1[i]); if (i < r1) f[lst][j][0] = f[lst][j][1] = inf; } swap(lst, nxt); } return ret; } inline int Cmp1(int x, int y) { return x1[x] < x1[y]; } inline int Cmp2(int x, int y) { return x2[x] < x2[y]; } int main() { int i, tb = 0, td = 0; scanf("%d%d%d%d%d%d%lf", &n, &m, &a, &b, &c, &d, &h), ++a, ++c; for (i = 1; i <= n; ++i) scanf("%lf", &x1[i]), id[i] = i; sort(id + 1, id + n + 1, Cmp1); for (i = 1; i <= n; ++i) { if (a == 1 && b == id[i] && !tb) b = i, tb = 1; if (c == 1 && d == id[i] && !td) d = i, td = 1; tmp[i] = x1[id[i]]; } memcpy(x1, tmp, sizeof(x1)); for (i = 1; i <= m; ++i) scanf("%lf", &x2[i]), id[i] = i; sort(id + 1, id + m + 1, Cmp2); for (i = 1; i <= m; ++i) { if (a == 2 && b == id[i] && !tb) b = i, tb = 1; if (c == 2 && d == id[i] && !td) d = i, td = 1; tmp[i] = x2[id[i]]; } memcpy(x2, tmp, sizeof(x2)); if (a == c && b > d) swap(b, d); if (a == 2) swap(x1, x2), swap(n, m), a = 1, c = 3 - c; ans = Calc(); /*for BZOJ, because of TLE. QwQ if (n >= 9000 && m >= 9000) return printf("%.2lf\n", ans), 0; */ if (a ^ c) swap(n, m), swap(b, d), swap(x1, x2), ans = min(ans, Calc()); printf("%.2lf\n", ans); return 0; }