[CF1455E] Four Points
Description
平面上有四个点,问最少移动多少步使得这四个点构成一个与座标轴平行正方形。
Solution
假设我们已经确定了四个顶点与最终的四个相对位置的对应关系
那么左边两个顶点要移动到同一列,需要花费的代价至少是它们之间横坐标的差的绝对值,其它四边同理
这时候,我们已经得到了形成一个长方形的代价
下面的问题是要把长方形变成正方形
我们先计算出原有的横向最小代价时的长度区间 [xl,xr],纵向的 [yl,yr]
如果这俩有交集,那么我们可以搞出一个正方形来
如果没有交集,那么我们需要花费额外的代价,即拉伸长方形的短边,此时付出的代价是 2 倍的区间距离
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define x first
#define y second
int eval(pair<int, int> p[4])
{
//0-LeftUp, 1-LeftDown, 2-RightUp, 3-RightDown
int ans = 0;
ans += abs(p[0].x - p[1].x);
ans += abs(p[3].x - p[2].x);
ans += abs(p[0].y - p[2].y);
ans += abs(p[1].y - p[3].y);
int xl = min(p[2].x, p[3].x) - max(p[0].x, p[1].x);
int xr = max(p[2].x, p[3].x) - min(p[0].x, p[1].x);
int yl = min(p[1].y, p[3].y) - max(p[0].y, p[2].y);
int yr = max(p[1].y, p[3].y) - max(p[0].y, p[2].y);
if (xl > yr || yl > xr)
ans += 2 * (max(xl, yl) - min(xr, yr));
return ans;
}
void solve()
{
pair<int, int> a[4]; //0-LeftUp, 1-LeftDown, 2-RightUp, 3-RightDown
for (int i = 0; i < 4; i++)
cin >> a[i].x >> a[i].y;
vector<int> perm(4);
iota(perm.begin(), perm.end(), 1);
int ans = 1e18;
do
{
pair<int, int> p[4];
for (int i = 0; i < 4; i++)
p[i] = a[perm[i] - 1];
ans = min(ans, eval(p));
} while (next_permutation(perm.begin(), perm.end()));
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--)
solve();
}