图中都是边长1千米的的等边三角形。每个数字都是在这个等边三角形的外心上,求给出两个数字间的最短距离。(直接连线的长度,最短)
从图中可以看出每行数字个数分别为1,3,5,7,9.。。。。然后我们就从等差数列求和公式得到求和公式f(n) = n^2.所以我们可以求出任意一个数字所在的行,和在这一行中的第几个数。也就是代码中的GetPos()函数。
有了这些信息,我们在看看每行的三角形,有头向上的有头向下的,可以发现,每行的列是奇数的就是向上的,偶数向下,因为外心不是三角的中心,所以要根据三角形的朝向来计算。
有了这些信息,我们就可以连接两点,构造一个直角三角形,计算两点之间的距离。
具体见代码。注意要用long long 啊。因为这里我计算位置的时候n++,如果最大的数+1就超过范围了。
#include <iostream> #include <cmath> #include <cstdio> #include <cstdlib> using namespace std; typedef struct Pos { long long row; long long col; }POS; POS GetPos(long long n) { n ++; POS pos; long long k = (long long)sqrt((double)n); if (k * k == n) { pos.row = k; pos.col = 2 * k - 1; } else if (k * k < n) { pos.row = k + 1; pos.col = n - k * k; } return pos; } long long Swap(long long *n, long long *m) { long long p; if (*n > *m) { p = *n; *n = *m; *m = p; } return 1; } int main() { long long n,m; POS posn,posm; while (scanf("%lld %lld", &n, &m) != EOF) { if (n == m) { printf("0.000\n"); continue; } Swap(&n, &m); posn = GetPos(n); posm = GetPos(m); if (posn.row == posm.row) { if (posm.col - posn.col == 1) { printf("0.577\n"); } else { double tmp = (posm.col - posn.col)/2.0; if ((posn.col % 2) ^ (posm.col % 2)) { printf("%.3f\n",sqrt(tmp * tmp + 1.0 / 12.0)); } else printf("%.3f\n",tmp); } } else { long long col; long long row = posm.row - posn.row; col = posn.col + row; //prlong longf("%d\n", col); double x, y, delta, delta1; x = fabs((double)(posm.col - col)) / 2.0; if (posn.col % 2) delta = sqrt(3.0) / 6.0; else delta = sqrt(3.0) / 3.0; if(posm.col % 2) delta1 = sqrt(3.0) / 3.0; else delta1 = sqrt(3.0) / 6.0; y = delta + delta1 + (row - 1) * sqrt(3.0) / 2.0; printf("%.3f\n", sqrt(x * x + y * y)); } } return 0; }