AT-ABC-323F题解

· · 题解

题目传送门

简单的无障碍推箱子问题。赛时 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; } ```