题意:
你要在平面直角坐标系中行走,每一步可以上下左右四个方向任意移动 $1$,耗时 $k$ 秒。特别地,存在若干条快速通道,若该步起点和终点均满足 $x \equiv 0 \pmod{B}$ 或 $y \equiv 0 \pmod{B}$,则认为该步是在快速通道上进行,仅需耗时 $1$ 秒。询问从 $(S_x, S_y)$ 到 $(G_x, G_y)$ 最少需要多少秒。存在多组数据。
思路:
看这个题第一眼没什么思路,先尝试画个图。
不难发现可以分类讨论。
首先有两种基本情况:
- 走通道
- 不走通道
对于走通道这种情况,我们可以分别枚举起点和终点向上、下、左、右的哪一个方向走到达快速通道的距离最短,然后将过起点或终点作垂直于距离最短的快速通道的垂线段的垂足的平面距离与两条垂线段的长度乘以 $k$ 的值相加,即可得到走通道的最短时间。再将这个时间与不走通道的最短时间取个最小值即可。
对于不走通道这种情况,我们可以直接计算,注意特判一下起点和终点都在同一行或同一列的快速通道上的情况即可。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int T,b,k,sx,sy,gx,gy;
int dis(int x_1,int y_1,int x_2,int y_2){
if(x_1%b==0&&x_2%b==0&&y_1/b==y_2/b) return min(abs(x_1-x_2)+min(y_1%b+y_2%b,b*2-y_1%b-y_2%b),abs(y_1-y_2)+abs(x_1-x_2)*k);
swap(x_1,y_1),swap(x_2,y_2);
if(x_1%b==0&&x_2%b==0&&y_1/b==y_2/b) return min(abs(x_1-x_2)+min(y_1%b+y_2%b,b*2-y_1%b-y_2%b),abs(y_1-y_2)+abs(x_1-x_2)*k);
return abs(x_1-x_2)+abs(y_1-y_2);
}
signed main(){
scanf("%lld",&T);
while(T--){
scanf("%lld%lld%lld%lld%lld%lld",&b,&k,&sx,&sy,&gx,&gy);
if(sx==gx&&sy==gy) printf("0\n");
else{
int res=dis(sx,sy,gx,gy)*k;
int sup=(sy/b+1)*b,sdo=sy/b*b;
int sri=(sx/b+1)*b,sle=sx/b*b;
int gup=(gy/b+1)*b,gdo=gy/b*b;
int gri=(gx/b+1)*b,gle=gx/b*b;
res=min(res,dis(sx,sup,gx,gup)+(sup-sy)*k+(gup-gy)*k);//起点向上终点向上
res=min(res,dis(sx,sup,gx,gdo)+(sup-sy)*k+(gy-gdo)*k);//起点向上终点向下
res=min(res,dis(sx,sup,gle,gy)+(sup-sy)*k+(gx-gle)*k);//起点向上终点向左
res=min(res,dis(sx,sup,gri,gy)+(sup-sy)*k+(gri-gx)*k);//起点向上终点向右
res=min(res,dis(sx,sdo,gx,gup)+(sy-sdo)*k+(gup-gy)*k);//起点向下终点向上
res=min(res,dis(sx,sdo,gx,gdo)+(sy-sdo)*k+(gy-gdo)*k);//起点向下终点向下
res=min(res,dis(sx,sdo,gle,gy)+(sy-sdo)*k+(gx-gle)*k);//起点向下终点向左
res=min(res,dis(sx,sdo,gri,gy)+(sy-sdo)*k+(gri-gx)*k);//起点向下终点向右
res=min(res,dis(sle,sy,gx,gup)+(sx-sle)*k+(gup-gy)*k);//起点向左终点向上
res=min(res,dis(sle,sy,gx,gdo)+(sx-sle)*k+(gy-gdo)*k);//起点向左终点向下
res=min(res,dis(sle,sy,gle,gy)+(sx-sle)*k+(gx-gle)*k);//起点向左终点向左
res=min(res,dis(sle,sy,gri,gy)+(sx-sle)*k+(gri-gx)*k);//起点向左终点向右
res=min(res,dis(sri,sy,gx,gup)+(sri-sx)*k+(gup-gy)*k);//起点向右终点向上
res=min(res,dis(sri,sy,gx,gdo)+(sri-sx)*k+(gy-gdo)*k);//起点向右终点向下
res=min(res,dis(sri,sy,gle,gy)+(sri-sx)*k+(gx-gle)*k);//起点向右终点向左
res=min(res,dis(sri,sy,gri,gy)+(sri-sx)*k+(gri-gx)*k);//起点向右终点向右
printf("%lld\n",res);
}
}
return 0;
}
标签:sy,sx,min,题解,gy,gx,ABC258F,res,Main
From: https://www.cnblogs.com/PerchLootie/p/18079144