Educational Codeforces Round 99 (Rated for Div. 2) 全文见:https://blog.csdn.net/qq_43461168/article/details/113105113
E. Four Points
题意:给四个点。移动他们,使得形成一个正方形。 求最小移动步数。
思路参考:https://www.cnblogs.com/qieqiemin/p/14069636.html
思路: x和y可以分开考虑。 首先枚举每个点作为四个点的任意一个点。也就是枚举所有排列。然后再进行计算。单独考虑x。设左下,右下,左上,右上,分别为 p0,p1,p2,p3。然后对于 p0-p2,可以求出一个x的范围 x1-x2。就是min(p0.x,p2.x) - max(p0.x,p2.x) 。同理对于 p1-p3 一样求。然后就会得出两个区间。 如果左边小于右边。那就让他们移动到各自的中点去就行了。这样移动距离是最小的。如果右边 小于左边。那就全部移动到min(p0.x,p2.x)就好了。边长为0也是合法的。对于y轴。是一样考虑的。这时候。得到了一个 水平的边长范围。和一个竖直的边长范围。如果 横着和竖着有交集。那就直接是 costx+costy。就是总的cost。如果没有交集。那必然需要两个点做出让步。移动到边长相等的地方去。这就加上额外的cost就行了。
AC代码:
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
using namespace std;
const int N = 1e6+7;
const int mod = 1e9+7;
int t = 1,n,m,k;
struct node{
int x,y;
}p[N];
int sum[N];
set<pair<int,int> > st;
signed main(){
cin>>t;
while(t-- ){
int b[] = {0,1,2,3};
for(int i = 0 ; i < 4 ; i ++){
cin>>p[i].x>>p[i].y;
}
int res = 1e18;
do{
int x1 = min(p[b[0]].x,p[b[2]].x);
int x2 = max(p[b[0]].x,p[b[2]].x);
int x3 = min(p[b[1]].x,p[b[3]].x);
int x4 = max(p[b[1]].x,p[b[3]].x);
int y1 = min(p[b[0]].y,p[b[1]].y);
int y2 = max(p[b[0]].y,p[b[1]].y);
int y3 = min(p[b[2]].y,p[b[3]].y);
int y4 = max(p[b[2]].y,p[b[3]].y);
int costx,costy;
int x_l,x_r,y_l,y_r;
if (x4 < x1) {
x_l = x_r = 0;
costx = x2 - x3 + x1 - x4;
} else {
x_l = max(x3 - x2, 0ll);
x_r = x4 - x1;
costx = x2 - x1 + x4 - x3;
}
if (y4 < y1) {
y_l = y_r = 0;
costy = y2 - y3 + y1 - y4;
} else {
y_l = max(y3 - y2, 0ll);
y_r = y4 - y1;
costy = y2 - y1 + y4 - y3;
}
int cost = costx + costy;
if (y_l > x_r) {
cost += (y_l - x_r) << 1;
} else if (x_l > y_r) {
cost += (x_l - y_r) << 1;
}
res = min(res, cost);
}while(next_permutation(b,b+4));
cout<<res<<endl;
}
return 0;
}