✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:蓝桥杯题解集合
📝原题地址:蜂巢
📣专栏定位:为想参加蓝桥别的小伙伴整理常考算法题解,祝大家都能取得理想成绩!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
问题描述
蜂巢由六边形拼接而成,定义蜂巢中的方向:0表示正西方向,1表示西偏北60°,2表示东偏北60°,3表示正东,4表示东偏南60°,5表示西偏南60°。
对于给定的一点O,以O为原点定义坐标系,如果一个点A由O点先向d方向走p步再向(d + 2) mod 6方向(d的顺时针120°向)走q步到达,则这个点的坐标定义为(d, p, q)。在蜂窝中,一个点的坐标可能有多种。 图给出了点B(0, 5, 3)和点C(2, 3, 2)的示意。
给定点(d1, p1, q1)和点(d2, p2, q2),请问他们之间最少走多少步可以到达?
输入格式
输入一行包含 6 个整数 d1,p1,q1,d2,p2,q2 表示两个点的坐标,相邻两个整数之间使用一个空格分隔。
输出格式
输出一行包含一个整数表示两点之间最少走多少步可以到达。
数据范围
对于 25% 的评测用例,p1,p2≤103;
对于 50% 的评测用例,p1,p2≤105;
对于 75% 的评测用例,p1,p2≤107;
对于所有评测用例,0≤d1,d2≤5,0≤q1<p1≤109,0≤q2<p2≤109。输入样例:
0 5 3 2 3 2
输出样例:
7
思路
这道题从图上来看其实并不难,假设我要从 B 到 C 找到最短路径,实际上就只能从右下走,但是难就难在这题没有给定坐标系,坐标系需要我们自己分析构建。
我们以 O 点为原点,以每个蜂巢的中心点作为每一处坐标,构建坐标系:
观察上图可知,如果直接用曼哈顿距离公式来计算两点之间的距离是不正确的,但可以发现如下规律(假设两点之间的横坐标之差的绝对值为 d x = ∣ x 1 − x 2 ∣ dx=|x1-x2| dx=∣x1−x2∣,纵坐标之差的绝对值为 d y = ∣ y 1 − y 2 ∣ dy=|y1-y2| dy=∣y1−y2∣):
- 如果
dx
大于dy
,则两点之间的距离为 ( d x + d y ) / 2 (dx+dy)/2 (dx+dy)/2 - 如果
dx
小于dy
,则两点之间的距离为 d y dy dy - 如果
dx
等于dy
,上面的两种公式都能得到正确答案
举个例子,假设从 (-1,1) 到 (1,-1),其 dx
和 dy
分别为 2 和 3。故 dy
大于 dx
,则最少要走 3
步。
再举个例子,假设从 (-1,1) 到 (2,0),其 dx
和 dy
分别为 3 和 1。故 dx
大于 dy
,则最少要走 (1+3)/2=2
步。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL d1, p1, q1, d2, p2, q2;
LL dx[] = { -2,-1,1,2,1,-1 }, dy[] = { 0,1,1,0,-1,-1 };
void walk(LL d, LL s, LL& x, LL& y)
{
x += dx[d] * s;
y += dy[d] * s;
}
int main()
{
cin >> d1 >> p1 >> q1 >> d2 >> p2 >> q2;
//计算第一个坐标
LL x1 = 0, y1 = 0;
walk(d1, p1, x1, y1);
walk((d1 + 2) % 6, q1, x1, y1);
//计算第二个坐标
LL x2 = 0, y2 = 0;
walk(d2, p2, x2, y2);
walk((d2 + 2) % 6, q2, x2, y2);
//计算dx和dy
LL dx = abs(x1 - x2), dy = abs(y1 - y2);
//根据计算结果输出对应答案
if (dx >= dy) cout << (dx + dy) / 2 << endl;
else cout << dy << endl;
return 0;
}