#include using namespace std; struct Pt{ double x, y, z; } A,B,C,D; const double eps = 1e-8; const double _5 = sqrt(5.0); const double _2 = sqrt(2.0); double f[3]; typedef pair PPP; struct Pi{ int x, y, z; }; bool operator < (const Pi & a, const Pi & b){ return (a.x < b.x); } bool operator == (const Pi & a, const Pi & b){ return (a.x == b.x && a.y == b.y && a.z == b.z); } void Pit(const Pt & X){ cout<> 1) & 1), X.z - 0.5 + ((k >> 2) & 1)}; } /******************************/ #ifdef SPFA #define MAXD 60 #else #define MAXD 30 #endif bool dis2_inRange(int x, int y, int z){ return 0 <= x && x <= MAXD && 0 <= y && y <= MAXD && 0 <= z && z <= MAXD; } inline double dis2_getDis(int cnt){ return cnt > 3 ? 1E100 : cnt == 3 ? _5 : cnt == 2 ? _2 : 1.0; } int dis2_getDis(int x, int y, int z, int ux, int uy, int uz){ const int t = -2; if (((x | 1) != (ux | 1) || (y | 1) != (uy | 1) || (z | 1) != (uz | 1)) && ((x + (x & 1)) != (ux + (ux & 1)) || (y + (y & 1)) != (uy + (uy & 1)) || (z + (z & 1)) != (uz + (uz & 1)))) return 4; return (x != ux) + (y != uy) + (z != uz); } void dis2_pre(Pi st, double (&dis)[MAXD + 1][MAXD + 1][MAXD + 1], int (&dt)[MAXD + 1][MAXD + 1][MAXD + 1][3]){ static bool in[MAXD + 1][MAXD + 1][MAXD + 1]; for (int i = 0; i <= MAXD; ++i) for (int j = 0; j <= MAXD; ++j) for (int k = 0; k <= MAXD; ++k){ dis[i][j][k] = 1E100; in[i][j][k] = false; dt[i][j][k][0] = dt[i][j][k][1] = dt[i][j][k][2] = 0; } dis[st.x][st.y][st.z] = 0; queue Q; Q.push(st); while (!Q.empty()){ Pi u = Q.front(); Q.pop(); // fprintf(stderr, "start update: %d %d %d\n", u.x, u.y, u.z); for (int i = -1; i <= 1; ++i) for (int j = -1; j <= 1; ++j) for (int k = -1; k <= 1; ++k){ int x = u.x + i, y = u.y + j, z = u.z + k; if (dis2_inRange(x, y, z)){ int tmp = dis2_getDis(u.x, u.y, u.z, x, y, z); if (dis[x][y][z] > dis[u.x][u.y][u.z] + dis2_getDis(tmp)){ dis[x][y][z] = dis[u.x][u.y][u.z] + dis2_getDis(tmp); dt[x][y][z][0] = dt[u.x][u.y][u.z][0]; dt[x][y][z][1] = dt[u.x][u.y][u.z][1]; dt[x][y][z][2] = dt[u.x][u.y][u.z][2]; ++dt[x][y][z][tmp - 1]; // printf("%d %d %d\n", x, y, z); if (!in[x][y][z]){ // puts("- ="); in[x][y][z] = true; Q.push((Pi){x, y, z}); } } } } in[u.x][u.y][u.z] = false; } } double dis2(Pi st, Pi ed){ static bool used = false; static double dis[8][MAXD + 1][MAXD + 1][MAXD + 1]; static int dt[8][MAXD + 1][MAXD + 1][MAXD + 1][3]; /* prework */ if (!used){ used = true; for (int i = 0; i < 8; ++i) dis2_pre((Pi){i >> 2 & 1, i >> 1 & 1, i & 1}, dis[i], dt[i]); } int dx = ed.x - st.x, dy = ed.y - st.y, dz = ed.z - st.z; if (dx < dy){ swap(dx, dy); swap(st.x, st.y); swap(ed.x, ed.y); } if (dx < dz){ swap(dx, dz); swap(st.x, st.z); swap(ed.x, ed.z); } if (dy < dz){ swap(dy, dz); swap(st.y, st.z); swap(ed.y, ed.z); } int cnt2 = 0, cnt1 = 0; #ifndef SPFA int Maki = 5; int tx = max(0, dx - Maki) & -4, ty = max(0, dy - Maki) & -4, tz = max(0, dz - Maki) & -4; // printf("%d %d %d\n", tx, ty, tz); dx -= tx, dy -= ty, dz -= tz; if (ty + tz <= tx){ tx -= cnt2 = ty + tz; cnt1 += max(0, tx - dy - dz); dx += min(dy + dz, tx); } else cnt2 += tx + ty + tz >> 1; // printf("- %d %d %d, %d %d\n", dx, dy, dz, cnt1, cnt2); // printf("st: %d %d %d\n", st.x, st.y, st.z); #endif ed.x = st.x + dx; ed.y = st.y + dy; ed.z = st.z + dz; int type = st.x << 2 | st.y << 1 | st.z; // printf("%d %d %d\n", cnt1 + dt[type][ed.x][ed.y][ed.z][0], cnt2 + dt[type][ed.x][ed.y][ed.z][1], dt[type][ed.x][ed.y][ed.z][2]); return cnt1 + cnt2 * _2 + dis[type][ed.x][ed.y][ed.z]; } #undef MAXD /******************************/ double _dis2(Pt P, Pt Q){ f[0] = fabs(P.x - Q.x); f[1] = fabs(P.y - Q.y); f[2] = fabs(P.z - Q.z); sort(f, f + 3); f[2] -= f[1]; f[1] -= f[0]; return _5 * f[0] + _2 * f[1] + f[2]; } Pt operator -(const Pt & a, const Pt & b){ return (Pt){a.x - b.x, a.y - b.y, a.z - b.z}; } Pt operator +(const Pt & a, const Pt & b){ return (Pt){a.x + b.x, a.y + b.y, a.z + b.z}; } Pt operator *(const Pt & a, double x){ return (Pt){a.x * x, a.y * x, a.z * x}; } double sqr(double x){ return x * x; } inline double len(const Pt & a){ return sqrt(sqr(a.x)+sqr(a.y)+sqr(a.z)); } double dg(double x, double y){ return sqrt(sqr(x) + sqr(y)); } PPP a[100]; int like(double p, double q, double r){ if (fabs(p - q) < eps && fabs(q - r) < eps) return 1; else return 0; } double le[100][100]; double Get_s(Pt p, Pt q){ for(int i = 0; i < 12; i++) for(int j = 0; j < 12; j++){ if (like(a[i].first.x, a[j].first.x, 0) || like(a[i].first.x, a[j].first.x, 1)) le[i][j] = len(a[i].first - a[j].first); else if (like(a[i].first.y, a[j].first.y, 0) || like(a[i].first.y, a[j].first.y, 1)) le[i][j] = len(a[i].first - a[j].first); else if (like(a[i].first.z, a[j].first.z, 0) || like(a[i].first.z, a[j].first.z, 1)) le[i][j] = len(a[i].first - a[j].first); else le[i][j] = 12345678; } for(int i = 0; i < 12; i++){ if (like(a[i].first.x, p.x, 0) ||like(a[i].first.x, p.x, 1) || like(a[i].first.y, p.y, 0) ||like(a[i].first.y, p.y, 1) || like(a[i].first.z, p.z, 0) ||like(a[i].first.z, p.z, 1)) le[i][13] = le[13][i] = len(p - a[i].first); else le[i][13] = le[13][i] = 12345678; if (like(a[i].first.x, q.x, 0) ||like(a[i].first.x, q.x, 1) || like(a[i].first.y, q.y, 0) ||like(a[i].first.y, q.y, 1) || like(a[i].first.z, q.z, 0) ||like(a[i].first.z, q.z, 1)) le[i][12] = le[12][i] = len(q - a[i].first); else le[i][12] = le[12][i] = 12345678; } le[13][13] = le[12][12] = 0; if (like(p.x, q.x, 0) || like(p.y, q.y, 0) || like(p.z, q.z, 0) || like(p.x, q.x, 1) || like(p.y, q.y, 1) || like(p.z, q.z, 1)) le[13][12] = le[12][13] = len(p - q); else le[13][12] = le[12][13] = 12345678; for(int k = 0; k < 14; k++) for(int i = 0; i < 14; i++) for(int j = 0; j < 14; j++) le[i][j] = min(le[i][j] , le[i][k] + le[k][j]); return le[12][13]; } double tf(Pt p, Pt q){ for(int i = 0; i <= 1; i++) for(int j = 0; j <= 1; j++) a[(i << 1) + j + 0] = (PPP){(Pt){i, j, rand()/(double)(RAND_MAX)}, (Pt){0, 0, 1}}; for(int i = 0; i <= 1; i++) for(int j = 0; j <= 1; j++) a[(i << 1) + j + 4] = (PPP){(Pt){i, rand()/(double)(RAND_MAX), j}, (Pt){0, 1, 0}}; for(int i = 0; i <= 1; i++) for(int j = 0; j <= 1; j++) a[(i << 1) + j + 8] = (PPP){(Pt){rand()/(double)(RAND_MAX), i, j}, (Pt){1, 0, 0}}; double now = Get_s(p, q); double t = 0.5; while(t > 0.001){ int flag = 0; for(int i = 0; i < 12; i++) if (!flag){ a[20] = a[i]; a[i].first = a[i].first + (a[i].second * t); double tmp = Get_s(p, q); if (tmp < now){ flag = 1; while(tmp < now){ now = tmp; a[20] = a[i]; a[i].first = a[i].first + (a[i].second * t); tmp = Get_s(p, q); } } a[i] = a[20]; } t *= 0.9; } return now; } double dis1(Pt P, Pt Q, Pt R){ // puts("QAQ"); P = P - R; Q = Q - R; P.x += 0.5, P.y += 0.5, P.z += 0.5; Q.x += 0.5, Q.y += 0.5, Q.z += 0.5; // Pit(P), Pit(Q); double ans = 10; for(int ts = 0; ts < 100; ts++){ // puts("= -"); ans = min(ans, tf(P, Q)); } // cout<<"tf:\t"< eps){ if (fabs(fabs(P.y) - 0.5) <= eps){ swap(P.y, P.x); swap(Q.y, Q.x); } else{ swap(P.z, P.x); swap(Q.z, Q.x); } } if (fabs(P.x + 0.5) < eps){ P.x = -P.x, Q.x = -Q.x; } if (fabs(Q.x - 0.5) < eps){//On the same face // cout<<"tl:\t"< eps){ swap(Q.y, Q.z); swap(P.y, P.z); } if (fabs(Q.y + 0.5) < eps){ Q.y = -Q.y, P.y = -P.y; } // cout<<"tl:\t"< eps){ if ((y & 1) != (x & 1)){ y = (int)(round(X.y * 2 - y)); } if ((z & 1) != (x & 1)){ z = (int)(round(X.z * 2 - z)); } } else{ if (fabs(fabs(fmod(X.y, 1)) - 0.5) > eps){ if ((y & 1) != (x & 1)){ x = (int)(round(X.x * 2 - x)); } if ((z & 1) != (y & 1)){ z = (int)(round(X.z * 2 - z)); } } else{ if ((z & 1) != (x & 1)){ x = (int)(round(X.x * 2 - x)); } if ((z & 1) != (y & 1)){ y = (int)(round(X.y * 2 - y)); } } } return (Pt){(double)x, (double)y, (double)z}; } double Nico(Pt P, Pt Q){ Pi p = (Pi){(int)(round(P.x + 0.5)), (int)(round(P.y + 0.5)), (int)(round(P.z + 0.5))}; Pi q = (Pi){(int)(round(Q.x + 0.5)), (int)(round(Q.y + 0.5)), (int)(round(Q.z + 0.5))}; q.x -= (p.x / 2) * 2, p.x -= (p.x / 2) * 2; if (p.x == -1){q.x += 2, p.x += 2;} q.y -= (p.y / 2) * 2, p.y -= (p.y / 2) * 2; if (p.y == -1){q.y += 2, p.y += 2;} q.z -= (p.z / 2) * 2, p.z -= (p.z / 2) * 2; if (p.z == -1){q.z += 2, p.z += 2;} if (q.x <= 0){ q.x = 1 - q.x; p.x = 1 - p.x; } if (q.y <= 0){ q.y = 1 - q.y; p.y = 1 - p.y; } if (q.z <= 0){ q.z = 1 - q.z; p.z = 1 - p.z; } return dis2(p, q); } void ck(double x){ assert(x >= -9999 && x <= 9999); } int main(){ // freopen("J.in", "r", stdin); // freopen("J.out", "w", stdout); // srand(time(NULL)); int T; scanf("%d",&T); /* for(int i = 0; i < 100; i++){ scanf("%lf%lf%lf", &A.x, &A.y, &A.z); scanf("%lf%lf%lf", &B.x, &B.y, &B.z); dis1(A, B, (Pt){0, 0, 0}); _dis1(A, B, (Pt){0, 0, 0}); } return 0; */ while(T--){ scanf("%lf%lf%lf", &A.x, &A.y, &A.z); scanf("%lf%lf%lf", &B.x, &B.y, &B.z); ck(A.x); ck(A.y); ck(A.z); ck(B.x); ck(B.y); ck(B.z); C = getcenter(A); assert((A.x - C.x - eps) <= 0.5 && (A.x - C.x + eps) >= -0.5); assert((A.y - C.y - eps) <= 0.5 && (A.y - C.y + eps) >= -0.5); assert((A.z - C.z - eps) <= 0.5 && (A.z - C.z + eps) >= -0.5); assert(((int)round(C.x - C.y)) % 2 == 0); assert(((int)round(C.x - C.z)) % 2 == 0); D = getcenter(B); assert((B.x - D.x - eps) <= 0.5 && (B.x - D.x + eps) >= -0.5); assert((B.y - D.y - eps) <= 0.5 && (B.y - D.y + eps) >= -0.5); assert((B.z - D.z - eps) <= 0.5 && (B.z - D.z + eps) >= -0.5); assert(((int)round(D.x - D.y)) % 2 == 0); assert(((int)round(D.x - D.z)) % 2 == 0); double ans = 1234567; if (C == D){ ans = _dis1(A, B, C); } else{ for(int i = 0; i < 8; i++) for(int j = 0; j < 8; j++){ // ans = min(ans,dis2(work(C, i), work(D, j))); // dis1(A, work(C, i), C); // _dis1(A, work(C, i), C); // dis1(B, work(D, j), D); // _dis1(B, work(D, j), D); ans = min(ans, _dis1(A, work(C, i), C) + _dis1(B, work(D, j), D) + Nico(work(C, i), work(D, j))); // ans = min(ans, dis1(A, work(C, i), C) + dis1(B, work(D, j), D) + dis2(work(C, i), work(D, j))); } } printf("%.16f\n", ans); } return 0; } /* 0.733017 0.493771 1 0.429134 0 0.88777 tf: 0.678462 tl: 0.677924 0.25458 0 1 0.165501 1 0.459615 tf: 1.4132 tl: 1.4108 0.561626 0 0 1 0.0775424 0.207269 tf: 0.556202 tl: 0.555994 0 0.98381 1 1 0.962809 0.831134 tf: 1.06045 tl: 1.05357 */