AT-ABC-323F题解
robertuu
·
·
题解
题目传送门
简单的无障碍推箱子问题。赛时 15 分钟秒了,发现洛谷上的大佬题解居然全是八种甚至十六种的大分讨,我就来了个三种的。
显然,把箱子调头是无意义的,箱子走的肯定是距离一定是 (X_B,Y_B) 和 (X_C,Y_C) 曼哈顿距离。
如果 (X_B,Y_B) 和 (X_C,Y_C) 不在同一条坐标轴上,人就需要花两步才能从横向推箱子变为纵向推箱子。
由于先横向和先纵向人初始需要去推箱子的位置不同。可以通过变量 X 和 Y 来保存目标点是在当前点的左或右、前或后,其实也是指示人应该站在性子的哪边推。
$X = 1$ 表示目标点在当前点的上方。
$Y = -1$ 表示目标点在当前点的右侧。
$Y = 1$ 表示目标点在当前点的左侧。
之后要处理的就是走到出发点(开始推箱子的点)。由于不能从箱子上走过,所以如果出发点、人、箱子横坐标或纵坐标一致,并且箱子在人和出发点之间,人就需要多走 $2$ 步绕开箱子,其他情况就是曼哈顿距离。可以通过函数完成。
```cpp
long long dist(long long xa,long long ya,long long xb,long long yb,long long xc,long long yc)
{
long long res = abs(xa-xb)+abs(ya-yb);
if(xa == xb && xb == xc && (ya < yc && yb > yc || ya > yc && yb < yc)) res += 2;
if(ya == yb && yb == yc && (xa < xc && xb > xc || xa > xc && xb < xc)) res += 2;
return res;
}
```
所以代码也很好写,分成横、纵、横纵都有就行了。
AC code:
```cpp
#include<bits/stdc++.h>
using namespace std;
long long dist(long long xa,long long ya,long long xb,long long yb,long long xc,long long yc)
{
long long res = abs(xa-xb)+abs(ya-yb);
if(xa == xb && xb == xc && (ya < yc && yb > yc || ya > yc && yb < yc)) res += 2;
if(ya == yb && yb == yc && (xa < xc && xb > xc || xa > xc && xb < xc)) res += 2;
return res;
}
int main()
{
long long xa,ya,xb,yb,xc,yc;
cin >> xa >> ya >> xb >> yb >> xc >> yc;
int X = 0,Y = 0;
if(xc > xb) X = -1;
if(xc < xb) X = 1;
if(yc > yb) Y = -1;
if(yc < yb) Y = 1;
if(X == 0) cout << dist(xa,ya,xb,yb+Y,xb,yb)+abs(yb-yc);
else if(Y == 0) cout << dist(xa,ya,xb+X,yb,xb,yb)+abs(xb-xc);
else cout << min(dist(xa,ya,xb,yb+Y,xb,yb),dist(xa,ya,xb+X,yb,xb,yb))+abs(yb-yc)+abs(xb-xc)+2;
return 0;
}
```