#include <stdio.h> #include <string.h> #include <math.h> #include <iostream> #include <algorithm>
using namespace std;
#define eps 1e-4 #define PI 3.1415927 #define G 9.18 #define N 15 #define zero(x) (((x)>0?(x):-(x))<eps) #define _sign(x) ((x)>eps?1:((x)<-eps?2:0))
struct point { double x, y; void out() { printf("%lf %lf\n", x, y); } };
struct dam_borad { double H, k; int len, type; point cor[N]; }dam[N];
double vx, vy, iniH, totTime; int n, cases;
double xmult(point p1, point p2, point p0) { return (p1.x - p0.x)* (p2.y-p0.y) - (p2.x - p0.x) * (p1.y - p0.y); }
int dots_inline(point p1, point p2, point p3) { return zero(xmult(p1, p2, p3)); }
int same_side(point p1, point p2, point l1, point l2) { return xmult(l1, p1, l2) * xmult(l1, p2, l2) > eps; }
int dot_online_in(point p, point l1, point l2) { return zero(xmult(p, l1, l2)) && (l1.x-p.x) * (l2.x-p.x) < eps && (l1.y-p.y) * (l2.y-p.y) < eps; }
int intersect_in(point u1, point u2, point v1, point v2) { if( !dots_inline(u1, u2, v1) || !dots_inline(u1, u2, v2)) return !same_side(u1, u2, v1, v2) && !same_side(v1,v2, u1, u2); return dot_online_in(u1,v1, v2) || dot_online_in(u2,v1, v2) || dot_online_in(v1,u1, u2) || dot_online_in(v2,u1, u2); }
point intersection(point u1, point u2, point v1, point v2) { point ret = u1; double t = (( u1.x - v1.x) * (v1.y - v2.y) - (u1.y - v1.y) * (v1.x - v2.x)) / (( u1.x - u2.x) * (v1.y - v2.y) - (u1.y - u2.y) * (v1.x - v2.x)); ret.x += (u2.x - u1.x) * t; ret.y += (u2.y - u1.y) * t; return ret; }
int inside_polygon(point q, int n) { int i , s[3] = {1, 1, 1}; for(i = 0; i < dam[n].len && s[1] | s[2]; i ++) { s[ _sign(xmult(dam[n].cor[i+1], q, dam[n].cor[i]))] = 0; } return s[1]|s[2]; }
int cmp(dam_borad a, dam_borad b) { return b.H - a.H < -eps; }
void read() { scanf("%lf %lf %lf", &vx, &vy, &iniH); scanf("%d", &n); for(int i = 0; i < n; i ++) { scanf("%lf", &dam[i].H); scanf("%d", &dam[i].len); for(int j = 0; j < dam[i].len; j ++) { scanf("%lf %lf", &dam[i].cor[j].x, &dam[i].cor[j].y); } dam[i].cor[dam[i].len] = dam[i].cor[0]; scanf("%d", &dam[i].type); scanf("%lf", &dam[i].k); } }
void init() { sort(dam, dam + n, cmp); totTime = 0; }
void drop() { int damNum = 0; point now, nowV; double nowH; now.x = now.y = 0; nowV.x = vx; nowV.y = vy; nowH = iniH; if(nowH < -eps) { totTime = -1; return; } while(damNum < n) { if( dam[damNum].H < eps) break; double detH = nowH - dam[damNum].H; if(detH < -eps) { damNum ++; continue; } double time = sqrt(2 * detH / G); point nowp, newp, end; newp.x = now.x + time * nowV.x; newp.y = now.y + time * nowV.y; if( inside_polygon(newp, damNum) ) { nowH = dam[damNum].H; totTime += time; if( dam[damNum].type == 0 ) { double tp1 = cos(dam[damNum].k), tp2 = sin(dam[damNum].k); double tempvx = nowV.x * tp1 - nowV.y * tp2; double tempvy = nowV.x * tp2 + nowV.y * tp1; nowV.x = tempvx; nowV.y = tempvy; } else if( dam[damNum].type == 1) { nowV.x = dam[damNum].k; } else if( dam[damNum].type == 2) { nowV.y = dam[damNum].k; } if(fabs(nowV.x) < eps && fabs(nowV.y) < eps) { totTime = -1; return; } end.x = newp.x + 1000 * nowV.x; end.y = newp.y + 1000 * nowV.y; now = newp; for(int i = 0; i < dam[damNum].len; i ++) { if( dot_online_in(newp, dam[damNum].cor[i], dam[damNum].cor[i + 1]) ) { point tp; tp.x = newp.x + nowV.x; tp.y = newp.y + nowV.y; if( dot_online_in(tp, dam[damNum].cor[i], dam[damNum].cor[i + 1]) ) { if( dot_online_in(dam[damNum].cor[i], newp, end) ) { now = dam[damNum].cor[i]; break; } else { now = dam[damNum].cor[i+1]; break; } } else { continue; } } if( intersect_in(newp, end, dam[damNum].cor[i], dam[damNum].cor[i + 1]) ) { now = intersection(newp, end, dam[damNum].cor[i], dam[damNum].cor[i + 1]); break; } } if( fabs(nowV.x) < eps ) totTime += fabs(now.y - newp.y) / fabs(nowV.y); else totTime += fabs(now.x - newp.x) / fabs(nowV.x); } damNum ++; } if(nowH > 0) { totTime += sqrt(2 * nowH / G); } }
void out() { printf("Case %d: ", cases++); if(totTime > -eps) printf("%.2lf\n", totTime); else printf("Forever!\n"); }
int main() { int t; scanf("%d", &t); cases = 1; while(t --) { read(); init(); drop(); out(); } }
|