[CF1455E] Four Points

[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();
}
原文地址:https://www.cnblogs.com/mollnn/p/14523192.html