题目: 蓝桥杯2022年第十三届省赛真题-蜂巢
最近在准备蓝桥杯的算法训练, 这道题思路感觉还是很巧妙, 但是C语言网 和 优快云上的解释都是十分的 粗略了, 注释很容易看不懂, 这篇文章算是抛砖引玉, 把自己的思考过程进行了分步复现, 总得来说 我感觉挺好理解的了~
问题:
蜂巢由大量的六边形拼接而成,定义蜂巢中的方向为: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) 的示意。
输入:
0 5 3 2 3 2
输出:
7
代码解释:
import java.util.Scanner;
/*
* 定义蜂巢中的方向为:
* 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)。
在蜂窝中,一个点的坐标可能有多种
给定点 (d1, p1, q1) 和点 (d2, p2, q2),
请问他们之间最少走多少步可以到达?
*/
public class Hive {
// 1. 将各个方向的单位移动距离 替换位 用新的十字坐标的单位移动距离
// 新的直角坐标系 的单位刻度解释:
// x 轴: 单位长度 为 1, 蜂巢的任何方向单位刻度都是1, 相同, 以此朝西运动1, 视为运用1个单位
// y 轴: 单位长度 为 √3/2, 蜂巢的任何方向单位刻度都是1, 因此, 朝西偏北运动1时, y轴上运动√3/2, 但在新坐标体系下, 运动为1个单位
// 数组的下标表示运动的方向, 数组的值表示在新直角坐标体系下运动的单位数
public static double[] x = new double[] {-1,-0.5,0.5,1,0.5,-0.5};
// 这里的y 单位长度为 √3/2, 1 表示一个单位长度
public static double[] y = new double[] {0,1,1,0,-1,-1};
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int d1 = in.nextInt();
int p1 = in.nextInt();
int q1 = in.nextInt();
int d2 = in.nextInt();
int p2 = in.nextInt();
int q2 = in.nextInt();
// 2. 在新坐标轴下确定两个点的坐标
double x1= x[d1]*p1 + x[(d1+2)%6]*q1;
double y1 = y[d1]*p1 + y[(d1+2)%6]*q1;
double x2 = x[d2]*p2 + x[(d2+2)%6]*q2;
double y2 = y[d2]*p2 + y[(d2+2)%6]*q2;
double deltaX = Math.abs(x1-x2); // x 轴的一个单位 ,可以是斜着2步 也可以是横着1步
double deltaY = Math.abs(y1-y2); // y 轴移动一个单位,需要至少斜着1步
// 2. 观察移动规律:
// 移动只有2种方式
// 第一种: 斜着移动: 同时来 x 与 y 轴的变化
// 第二中: 横着移动: 只会带来 x 轴的变化
// 移动的总步数 = 斜着 + 横着
int res = (int)deltaY; // 因为具有y轴差, 因此至少需要斜着走的步数
// 由于斜着走的步数 一定会带来 x 轴的变化;
// 根据 数组对比, 斜着走1步 一定会带来 0.5的x轴变化, 因此
// 如果 deltaX- deltaY/2 > 0, 说明即使斜着的步数走完后, x轴上依然有差距, 剩下的为x的步数
if (deltaX- deltaY/2 > 0) {
res = res + (int)Math.abs(deltaX - deltaY/2);
}
System.out.println(res);
}
}
总结
核心难点
- Java使用数组的方式建立相对坐标系
- 由于是求最短的步数, 可能被误导为动态规划问题
- 观察运动规律, 比如y轴的运动只能依赖斜着运动