问题描述
蜂巢由六边形拼接而成,定义蜂巢中的方向: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表示两个点的坐标, 相邻两个整 数之间使用一个空格分隔。
输出格式
输出一行包含一个整数表示两点之间最少走多少步可以到达。
样例输入
输入
0 5 3 2 3 2
输出
7
题解
1. 本题属于构造类型的题,比较难一点。
2. 我们可以尝试转换一下模型,无非就是求两个点之前的最短距离,但是走的步数需要按照他的来
3. 我们先将蜂巢转换为坐标的形式,这个地方不好想:
4. 我们以一个半长为1,这样避免分数,通过这样的图,我们很清楚知道了我们要求两个点的距离
5. 首先我们应该先将我们输入的值转换为这坐标轴上面的坐标,也就是通过题意可以得知,我们是通过d来定义方向的
6. 于是按照他的数字提前写两个列表,来表示每次向某个方位移动一步的坐标变化:
redx = [-2,-1,1,2,1,-1]
redy = [0,1,1,0,-1,-1]
7. 然后我们将我们的dpq转换为坐标值:
def run(d,p,x,y):
x += redx[d] *p
y += redy[d] *p
return x,y
x1,y1 = run(d1,p1,x1,y1)
x1,y1 = run((d1+2) % 6,q1,x1,y1)
x2,y2 = run(d2,p2,x2,y2)
x2,y2 = run((d2+2) % 6,q2,x2,y2)
整体来看,其实就移动了两步,所以可以定义一个函数,一个表示方向,一个表示步数
8. 找到坐标之后,我们就可以很清楚知道我们要求什么了,不过是两点的距离罢了,最短的无非就是平着走,然后再斜着走。
9. 于是咣咣写了下面代码,但是很遗憾只过了75%的样例
d1,p1,q1,d2,p2,q2 = map(int,input().split())
x1 = 0
y1 = 0
x2 = 0
y2 = 0
redx = [-2,-1,1,2,1,-1]
redy = [0,1,1,0,-1,-1]
def run(d,p,x,y):
x += redx[d] *p
y += redy[d] *p
return x,y
x1,y1 = run(d1,p1,x1,y1)
x1,y1 = run((d1+2) % 6,q1,x1,y1)
x2,y2 = run(d2,p2,x2,y2)
x2,y2 = run((d2+2) % 6,q2,x2,y2)
dx = abs(x1-x2)
dy = abs(y1-y2)
print((dx+dy)//2) # 这里//2的原因是,我们刚开始定义的一步其实坐标上面走了2格
10. 于是继续寻找另外的可能性
如果是这种情况的话,那么你两个直边相加//2的值是比直接走斜边要大的
11. 所以还有一种情况就是直接通过斜边来走,那么如何判断是否是直接在一条斜边上面呢?
12.
现在来看这张图,不难发现,如果你的dx>dy的话,也就是说,两个点之间的的横边大于竖直的边的话,那么这个你的斜边是不能连成一条线的,因此就得出了最后的代码:
代码
d1,p1,q1,d2,p2,q2 = map(int,input().split())
x1 = 0
y1 = 0
x2 = 0
y2 = 0
redx = [-2,-1,1,2,1,-1]
redy = [0,1,1,0,-1,-1]
def run(d,p,x,y):
x += redx[d] *p
y += redy[d] *p
return x,y
# 求最后两个点的坐标
x1,y1 = run(d1,p1,x1,y1)
x1,y1 = run((d1+2) % 6,q1,x1,y1)
x2,y2 = run(d2,p2,x2,y2)
x2,y2 = run((d2+2) % 6,q2,x2,y2)
dx = abs(x1-x2)
dy = abs(y1-y2)
if dx > dy: # 判断边长
print((dx+dy)//2)
else:
print(dy)