#include #include #include #include #include #include #include using namespace std; struct xyz{ double x, y, z; xyz(){} xyz(double x, double y, double z):x(x), y(y), z(z){} }; double distance_(const xyz& lhs, const xyz &rhs) { double dx = rhs.x - lhs.x; double dy = rhs.y - lhs.y; double dz = rhs.z - lhs.z; return sqrt(dx*dx + dy*dy + dz*dz); } struct pm{ xyz center; double msize; pm(){} pm(xyz center, double msize):center(center), msize(msize){} }; double INFTY = 999999.; double solve(vector &cs, vector& rs) { queue toBeProcessed; for(double x = 0.025; x < 1; x += 0.05){ for(double y = 0.025; y < 1; y += 0.05){ for(double z = 0.025; z < 1; z += 0.05){ toBeProcessed.push(pm(xyz(x, y, z), 0.025)); } } } double result = -INFTY; while(!toBeProcessed.empty()){ pm t = toBeProcessed.front(); toBeProcessed.pop(); xyz p = t.center; double mesh = t.msize; double half = mesh * .5; double diag = mesh * sqrt(3); // gcc extension (perhaps?) double v[] = { p.x, 1.-p.x, p.y, 1.-p.y, p.z, 1.-p.z }; double dmin = *min_element(v, v+6); for(int i = 0; i < cs.size(); ++i){ double d = distance_(p, cs[i]) - rs[i]; dmin = min(dmin, d); // the perfect insider :P if(d + diag < 0) goto next; } result = max(result, dmin); // no way! if(dmin + diag < result) continue; if(diag < 0.00005) continue; for(int i = 0; i < 8; ++i){ xyz newp; if(i & 1) newp.x = p.x + half; else newp.x = p.x - half; if(i & 2) newp.y = p.y + half; else newp.y = p.y - half; if(i & 4) newp.z = p.z + half; else newp.z = p.z - half; toBeProcessed.push(pm(newp, half)); } next:; } return result; } int main(void) { ifstream cin("balls.in"); int NCases; cin >> NCases; while(NCases--){ int N; cin >> N; vector centers; vector rs; for(int i = 0; i < N; ++i){ double x, y, z, r; cin >> x >> y >> z >> r; centers.push_back(xyz(x, y, z)); rs.push_back(r); } cout.setf(ios::fixed); cout << setprecision(6); cout << solve(centers, rs) << endl; } return 0; }