#include #include #include #include #include #include #include using namespace std; class Robot{ public: double x, y; int u; }; bool operator<(Robot a, Robot b){ return ((a.x < b.x) || ((a.x == b.x) && (a.y < b.y))); } struct MyYLess : public binary_function { bool operator()(const Robot& a, const Robot& b){ return (a.y < b.y); } }; double get_t(const Robot& a, const Robot& b, double r, double v){ double D = 4*r*r - (a.y-b.y)*(a.y-b.y); if (D < 0) return DBL_MAX; double t1 = (b.x-a.x+sqrt(D))/(2*v); double t2 = (b.x-a.x-sqrt(D))/(2*v); if (t1 < 0) return DBL_MAX; else if (t2 < 0) return t1; else return t2; } int main(){ int N; while(true/*cin >> N*/){ scanf("%d", &N); if (N == 0) break; double vx, vy; //cin >> vx >> vy; scanf("%lf %lf", &vx, &vy); double r; //cin >> r; scanf("%lf", &r); vector robots_vector; for (int i = 0; i < N; i++){ Robot temp_robot; //cin >> temp_robot.x >> temp_robot.y >> temp_robot.u; scanf("%lf %lf %d", &(temp_robot.x), &(temp_robot.y), &(temp_robot.u)); robots_vector.push_back(temp_robot); } double v = sqrt(vx*vx + vy*vy); double c = vx/v; double s = vy/v; for (int i = 0; i < N; i++){ double x_backup = robots_vector[i].x; double y_backup = robots_vector[i].y; robots_vector[i].x = c*x_backup - (-s)*y_backup; robots_vector[i].y = (-s)*x_backup + c*y_backup; } sort(robots_vector.begin(), robots_vector.end(), MyYLess()); set s1, s_1; double crash_time = DBL_MAX; int now_begin = 0; int now_end = 0; do{ set new_inserted; while((now_end < (int)robots_vector.size()) && (robots_vector[now_end].y - robots_vector[now_begin].y) <= 2*r){ if (robots_vector[now_end].u == 1){ s1.insert(robots_vector[now_end]); }else{ s_1.insert(robots_vector[now_end]); } new_inserted.insert(robots_vector[now_end]); now_end++; } for (set::iterator iter = new_inserted.begin(); iter != new_inserted.end(); iter++){ if ((*iter).u == 1){ s_1.insert(*iter); set::iterator now_target = ++(s_1.find(*iter)); for (int i = 0; (now_target != s_1.end()) && (i < 3); now_target++, i++){ crash_time = min(crash_time, get_t(*iter, *now_target, r, v)); } s_1.erase(*iter); }else{ s1.insert(*iter); set::iterator now_target = s1.find(*iter); if (now_target != s1.begin()){ now_target--; for (int i = 0; i < 3; now_target--, i++){ crash_time = min(crash_time, get_t(*now_target, *iter, r, v)); if (now_target == s1.begin()) break; } } s1.erase(*iter); } } while((now_end < (int)robots_vector.size()) && (robots_vector[now_end].y - robots_vector[now_begin].y) > 2*r){ if (s1.find(robots_vector[now_begin]) != s1.end()){ s1.erase(robots_vector[now_begin]); }else if (s_1.find(robots_vector[now_begin]) != s_1.end()){ s_1.erase(robots_vector[now_begin]); } now_begin++; } }while(now_end < (int)robots_vector.size()); if (crash_time == DBL_MAX) printf("SAFE\n"); else printf("%.6llf\n",crash_time); } return 0; }