平面上一開始有三個點\((0,0),(0,1),(1,0)\)形成成L形(點連續),每次操作可以將一個點改變位置,使得得到的仍然是L形。給出終止L形的位置,問移動的最小步數。
\(|x|,|y|\le 10^9,T\le 10^3\)
有若干種陰間的分類討論做法但是陽間的做法卻不好想。
CF論壇中的一位大佬分享了個clean solution:
考慮\(L\)形重心的位置,考慮每次移動重心是怎樣移動的,可以發現:重心能往8聯通方向除了跨過頂點的方向外移動一格。
於是先把L形的坐標轉化成重心的坐標,假如是8聯通,那么答案為\(\max(|X|,|Y|)\)。加上走的過程中不能跨過頂點的限制,可以發現如果\(X\neq Y\)則仍然可以走過去,如果\(X=Y\)就需要偏離一下,然后后面也可以直接走過去,代價\(+1\)。
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define x first
#define y second
pair<int,int> d[3];
ll X,Y;
void trans(){
sort(d,d+3);
if (d[0].x==d[1].x && d[0].y==d[2].y){
X=d[0].x*2;
Y=d[0].y*2;
}
else if (d[1].x==d[2].x && d[1].y==d[0].y){
X=d[1].x*2-1;
Y=d[1].y*2;
}
else if (d[1].x==d[0].x && d[1].y==d[2].y){
X=d[1].x*2;
Y=d[1].y*2-1;
}
else{//d[2].x==d[1].x && d[2].y==d[0].y
X=d[2].x*2-1;
Y=d[2].y*2-1;
}
}
int main(){
int T;
scanf("%d",&T);
while (T--){
for (int i=0;i<3;++i)
scanf("%lld%lld",&d[i].x,&d[i].y);
trans();
ll ans=max(abs(X),abs(Y));
if (X==Y && X!=0 && X!=1)
ans++;
printf("%lld\n",ans);
}
return 0;
}