小F最近在研究蜂巢,如下图所示,这是一个蜂巢的横剖图,每一个格子都是一个正六边形,多个格子平铺构成一个无限大的平面。我们以中央的格子作为原点,按照下图规律,一圈一圈向外将每个格子都编上号。
小F想知道,如果一个蜜蜂当前在编号为x的格子处,它想到达编号为y的格子,最优情况下它最少需要经过多少个格子(包含起点终点)。蜜蜂在蜂巢里只能爬行,也就是说它每次只能爬到相邻的格子里。
你需要支持多组询问。
题意:
题目写得很明白()
题解:
直接建坐标系,六边形有三个轴,任选其中两个轴建系即可(某憨憨不想写太多特判然后建了两个系)
然后注意要加特判,具体形式就是正三角形内的两点距离要特判(见代码)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const ll N = 2e5 + 7, M = 1e9 + 7;
ll x[N], xn[N], y1_[N], y1n[N], y2[N], y2n[N];
ll xx1, xx2, yy;
void pre() {
x[0] = xn[0] = y1_[0] = y1n[0] = y2[0] = y2n[0] = 1;
for (ll i = 1; i < N; i++) {
x[i] = x[i - 1] - 1 + i * 6;
xn[i] = xn[i - 1] + i * 6 - 4;
y1_[i] = y1_[i - 1] - 2 + i * 6;
y1n[i] = y1n[i - 1] - 5 + i * 6;
y2[i] = y2[i - 1] + i * 6 - 3;
y2n[i] = y2n[i - 1] + i * 6 - 0;
}
}
void pos(ll ind) {
if (ind == 1) {
xx1 = xx2 = yy = 0;
return;
}
int xi = lower_bound(y2n, y2n + N, ind) - y2n;
if (ind >= x[xi]) {
xx1 = xi;
int k = ind - x[xi];
xx2 = xi - k;
yy = -k;
}
else if (ind >= y1_[xi]) {
int k = x[xi] - ind;
yy = k;
xx1 = xi - k;
xx2 = xi;
}
else if (ind >= y2[xi]) {
int k = y1_[xi] - ind;
xx1 = -k;
xx2 = xi - k;
yy = xi;
}
else if (ind >= xn[xi]) {
xx1 = -xi;
int k = ind - xn[xi];
xx2 = -xi + k;
yy = k;
}
else if (ind >= y1n[xi]) {
int k = xn[xi] - ind;
xx2 = -xi;
xx1 = -xi + k;
yy = -k;
}
else {
int k = y1n[xi] - ind;
xx1 = k;
xx2 = k - xi;
yy = -xi;
}
}
int main() {
ll T;
cin >> T;
pre();
while (T--) {
ll a, b;
cin >> a >> b;
pos(a);
ll xa1 = xx1, xa2 = xx2, ya = yy;
//printf("%lld %lld %lld\n", xa1, xa2, yy);
pos(b);
ll xb1 = xx1, xb2 = xx2, yb = yy;
//printf("%lld %lld %lld\n", xb1, xb2, yy);
ll suby = abs(ya - yb);
ll subx1 = abs(xa1 - xb1), subx2 = abs(xa2 - xb2);
if (suby) {
if (xa1 > xb1 && ya < yb && subx1 <= suby) {
subx1 = 0;
}
else if (xa1<xb1&& ya>yb&& subx1 <= suby) {
subx1 = 0;
}
if (xa2 > xb2 && ya > yb && subx2 <= suby) {
subx2 = 0;
}
else if (xa2 < xb2 && ya < yb && subx2 <= suby) {
subx2 = 0;
}
}
ll ans = min(subx1 + suby, subx2 + suby);
cout << ans + 1 << endl;
}
}