1455E Four Points(思维+全排列)
Educational Codeforces Round 99 (Rated for Div. 2)
E. Four Points
题面:Four Points
题意:二维平面上有四个点 p 1 , p 2 , p 3 p_1, p_2, p_3 p1,p2,p3 和 p 4 p_4 p4,现在想让这四个点形成与坐标轴平行的正方形(正方形也可以是一个点),每次操作可以让其中一个点往上下左右移动一个单位距离,问最小的操作次数是多少。
范围: p i = ( x i , y i ) , 0 ≤ x , y ≤ 1 e 9 p_i = (x_i, y_i), 0 \le x, y \le 1e9 pi=(xi,yi),0≤x,y≤1e9。
分析: 先简化问题,假设这四个点分别对应正方形的 a , b , c , d a, b, c, d a,b,c,d 如下四个顶点,那么如何快速求得答案,即这四个点分别到 a , b , c , d a, b, c, d a,b,c,d 的曼哈顿距离之和。
首先,不失一般性,我们可以认为点先到达线段所在直线上,再移动到最终的顶点位置,假设我们需要确定线段 a b ab ab,当这条线段位于 p 1 p_1 p1 与 p 2 p_2 p2 两个点的中间的时候, p 1 p_1 p1 和 p 2 p_2 p2 到该线段的距离和最小,选择区间为 [ p 1 . x , p 2 . x ] [p_1.x, p_2.x] [p1.x,p2.x]。
对于另一条边 c d cd cd 也是同样的道理, c d cd cd 的选择区间为 [ p 3 . x , p 4 . x ] [p_3.x, p_4.x] [p3.x,p4.x] 中时 p 3 p_3 p3 和 p 4 p_4 p4 到 c d cd cd 的距离和最小。
在选定 a b ab ab 和 c d cd cd 之后就可以确定正方形的边长为 l e n ∈ [ l e n 1 , l e n 2 ] len \in [len_1, len_2] len∈[len1,len2] 如下图所示。
同理,选定 a c ac ac 和 b d bd bd 两条水平的边也可以确定正方形的边长 l e n ′ ∈ [ l e n 3 , l e n 4 ] len' \in [len_3, len_4] len′∈[len3,len4]。
当区间 [ l e n 1 , l e n 2 ] [len_1, len_2] [len1,len2] 与区间 [ l e n 3 , l e n 4 ] [len_3, len_4] [len3,len4] 有交集的时候,说明存在一个边长 l e n len len 同时满足两者的最优解,输出距离和即可。如果没有交集的话,不失一般性,假设 l e n 3 > l e n 2 len_3 > len_2 len3>len2,即区间 [ l e n 3 , l e n 4 ] [len_3, len_4] [len3,len4] 在区间 [ l e n 1 , l e n 2 ] [len_1, len_2] [len1,len2] 的右边如下图。
显然,这时只有当正方形的边长为 l e n 2 len_2 len2 或者 l e n 3 len_3 len3 时才能得到整体的最优解,但是需要多支出 2 ∗ d i s t 2 * dist 2∗dist 的代价,因为需要 2 2 2 个点多移动 d i s t dist dist 的距离。
到此,固定了 p 1 , p 2 , p 3 , p 4 p_1, p_2, p_3, p_4 p1,p2,p3,p4 四个点与正方形四个顶点的对应关系下的最优解问题已经解决,但是实际上的对应关系我们还无法确定,因为只有四个点,直接进行 n e x t _ p e r m u t a t i o n next\_permutation next_permutation 全排列枚举取最优解即可。
Code:
#include <bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
inline int read()
{
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
const int MAXN = 4 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1.0);
int n, m, k;
struct Point
{
int x, y;
} points[MAXN];
int arr[MAXN];
int calc()
{
Point ld = points[arr[0]], lu = points[arr[1]],
rd = points[arr[2]], ru = points[arr[3]];
int seg_xl = min(abs(max(ld.x, lu.x) - min(rd.x, ru.x)),
abs(min(ld.x, lu.x) - max(rd.x, ru.x)));
int seg_xr = max(abs(max(ld.x, lu.x) - min(rd.x, ru.x)),
abs(min(ld.x, lu.x) - max(rd.x, ru.x)));
int seg_yl = min(abs(max(ld.y, rd.y) - min(lu.y, ru.y)),
abs(min(ld.y, rd.y) - max(lu.y, ru.y)));
int seg_yr = max(abs(max(ld.y, rd.y) - min(lu.y, ru.y)),
abs(min(ld.y, rd.y) - max(lu.y, ru.y)));
int res = max(ld.x, lu.x) - min(ld.x, lu.x) +
max(rd.x, ru.x) - min(rd.x, ru.x) +
max(ld.y, rd.y) - min(ld.y, rd.y) +
max(lu.y, ru.y) - min(lu.y, ru.y) +
2 * max(0ll, max(seg_xl, seg_yl) - min(seg_xr, seg_yr));
return res;
}
signed main()
{
int T = read();
while (T--)
{
for (int i = 0; i < 4; i++)
{
points[i].x = read(), points[i].y = read();
}
for (int i = 0; i < 4; i++)
{
arr[i] = i;
}
int ans = -1;
do
{
if (ans < 0) ans = calc();
else ans = min(ans, calc());
} while (next_permutation(arr, arr + 4));
cout << ans << endl;
}
return 0;
}
【END】感谢观看