题意:给定一个蜂窝,按如图规则给每个六边形孔顺时针绕圈标号,问某两个标号之间的距离。
分析:把每个六边形看作正方形,并建立平面直角坐标系。1号位于(0,0)。x轴从左上到右下方向,y轴从左下到右上方向。然后将图转化为正方形的图。对于一个给定的编号利用公式计算是第几圈的,再算是6条边中哪条边的,再计算坐标。两个点之间的行走规则是,先将图看作正方形组成,可走正方形横竖相邻的正方形,也可走其捺对角线,但不能走其撇对角线。
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
struct Point
{
int x, y;
};
int a, b;
Point cal(int a)
{
Point ret;
if (a == 1)
{
ret.x = 0;
ret.y = 0;
return ret;
}
int n = sqrt((a - 1) / 3);
while (3 * (n - 1) * n + 1 < a)
n++;
while (3 * (n - 1) * n + 1 >= a)
n--;
a -= 3 * (n - 1) * n + 1;
if (a <= n)
{
ret.x = n;
ret.y = -a;
}else if (a > n && a <= 2 * n)
{
ret.x = n - a + n;
ret.y = -n;
}else if (a > 2 * n && a <= 3 * n)
{
ret.x = 2 * n - a;
ret.y = -n - ret.x;
}else if (a > 3 * n && a <= 4 * n)
{
ret.x = -n;
ret.y = a - 3 * n;
}else if (a > 4 * n && a <= 5 * n)
{
ret.x = (a - 4 * n) - n;
ret.y = n;
}else
{
ret.x = a - 5 * n;
ret.y = n - ret.x;
}
return ret;
}
int main()
{
//freopen("t.txt", "r", stdin);
while (scanf("%d%d", &a, &b), a | b)
{
Point p = cal(a);
Point q = cal(b);
Point ans;
ans.x = p.x - q.x;
ans.y = p.y - q.y;
int temp;
if (ans.x * ans.y <= 0)
temp = max(abs(ans.x), abs(ans.y));
else
temp = abs(ans.x + ans.y);
printf("The distance between cells %d and %d is %d.\n", a, b, temp);
}
return 0;
}