题意:
给出四个点的坐标,我们一次操作可以将其中一个点向上下左右任意一个方向移动一个单位,为最少要多少次操作才能使得四个点组成平行于x轴和y轴的正方形。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int MAXN=1e5+5;
const int mod=1e9+7;
struct node
{
int x,y;
}f[10];
int cnt[10];
int solve(int x1,int y1,int x2,int y2)
{
if(x2>y1) return -1;
else if(y2<x1) return -2;
else return 1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
for(int i=1;i<=4;i++)
{
cnt[i]=i;
}
for(int i=1;i<=4;i++)
{
scanf("%d%d",&f[i].x,&f[i].y);
}
ll ans=1e18;
do
{
int l1=min(f[cnt[1]].x,f[cnt[2]].x);
int r1=max(f[cnt[1]].x,f[cnt[2]].x);
int l2=min(f[cnt[3]].x,f[cnt[4]].x);
int r2=max(f[cnt[3]].x,f[cnt[4]].x);
int len1=min(abs(r1-l2),abs(l1-r2));
len1=min(abs(r1-l2),abs(r1-r2));
int len2=max(abs(r1-l2),abs(l1-r2));
len2=max(abs(r1-l2),abs(r1-r2));
int le1=min(f[cnt[1]].y,f[cnt[3]].y);
int ri1=max(f[cnt[1]].y,f[cnt[3]].y);
int le2=min(f[cnt[2]].y,f[cnt[4]].y);
int ri2=max(f[cnt[2]].y,f[cnt[4]].y);
int len3=min(abs(ri1-le2),abs(le1-ri2));
len3=min(abs(ri1-le2),abs(ri1-ri2));
int len4=max(abs(ri1-le2),abs(le1-ri2));
len4=max(abs(ri1-le2),abs(ri1-ri2));
if(solve(len1,len2,len3,len4)==1)
{
ll res=1ll*(r1-l1)+1ll*(r2-l2)+1ll*(ri1-le1)+1ll*(ri2-le2);
ans=min(ans,res);
}
else if(solve(len1,len2,len3,len4)==-1)
{
ll res=1ll*(r1-l1)+1ll*(r2-l2)+1ll*(ri1-le1)+1ll*(ri2-le2);
res+=2ll*(len3-len2);
ans=min(ans,res);
}
else
{
ll res=1ll*(r1-l1)+1ll*(r2-l2)+1ll*(ri1-le1)+1ll*(ri2-le2);
res+=2ll*(len1-len4);
ans=min(ans,res);
}
//cout<<r1-l1+r2-l2+ri1-le1+ri2-le2<<endl;
//cout<<len1<<" "<<len2<<" "<<len3<<" "<<len4<<endl;
//cout<<solve(len1,len2,len3,len4)<<endl;
}while(next_permutation(cnt+1,cnt+1+4));
printf("%lld\n",ans);
}
}