#include #include #include #include using namespace std; //double の複素数、位置と速度という二つの意味で使う typedef complex cd; //線分 typedef pair line; //折れ線 typedef vector poly; //移動 first の時間まで second 方向に移動する typedef pair move; //移動のリスト typedef vector movelist; //衝突しない場合用の十分大きな時間 #define NO_CLASH_TIME 1e+8 //イプシロン #define EPSILON 1e-6 /*************************************** 位置 p2 から出発した点が速度 v2 で period 時間移動したとき 線分 line1 と交差する時間 t, s:実数 p1, v1, p2, v2:複素数 線分 line1 の媒介変数表現 p1 + t v1 (0 <= t <= 1) 移動する点の軌跡の媒介変数表現 p2 + s v2 (0 <= s <= period) 移動する点が線分と交差するときに満たすべき方程式 p1 + t v1 = p2 + s v2 (0 <= t <= 1, 0 <= s <= period) p1 の移項 t v1 = (p2 - p1) + s v2 両辺を v2 で割る t v1/v2 = (p2 - p1)/v2 + s 両辺の虚数成分をとる、s, t は実数 t imag{v1/v2} = imag{(p2-p1)/v2} 両辺を imag{v1/v2} で割る t = imag{(p2-p1)/v2} / imag{v1/v2} */ double clashtime_sub_sub(line line1, cd p2, cd v2, double period) { cd p1 = line1.first; cd v1 = line1.second - line1.first; if(abs(imag(v2 / v1)) < EPSILON)return NO_CLASH_TIME; double s = imag((p1-p2)/v1) / imag(v2/v1); double t = imag((p2-p1)/v2) / imag(v1/v2); if(s < 0.0 || period < s || t < 0.0 || 1.0 < t)return NO_CLASH_TIME; return s; } /*************************************** 速度 v1 で移動する線分 line1 と 速度 v2 で移動する線分 line2 が 期間 period 間で最初に衝突する時間 4つの場合わけで解いている 解説スライド参照 */ double clashtime_sub(line line1, cd v1, line line2, cd v2, double period) { double ans = NO_CLASH_TIME; ans = min(ans, clashtime_sub_sub(line1, line2.first , v2-v1, period)); ans = min(ans, clashtime_sub_sub(line1, line2.second, v2-v1, period)); ans = min(ans, clashtime_sub_sub(line2, line1.first , v1-v2, period)); ans = min(ans, clashtime_sub_sub(line2, line1.second, v1-v2, period)); return ans; } /*************************************** 折れ線移動する2つの線分を 同じ移動している時間に区切って衝突時間を求める */ double clashtime(line line1, movelist move1, line line2, movelist move2){ movelist::iterator it1 = move1.begin(); movelist::iterator it2 = move2.begin(); double now = 0.0; while(it1 != move1.end() && it2 != move2.end() && now < NO_CLASH_TIME) { double nextnow = min(it1->first, it2->first); double period = nextnow - now; cd v1 = it1->second; cd v2 = it2->second; double time = clashtime_sub(line1, v1, line2, v2, period); if(time < NO_CLASH_TIME)return time + now; if(it1->first == nextnow)it1++; if(it2->first == nextnow)it2++; line1.first += v1 * period; line1.second += v1 * period; line2.first += v2 * period; line2.second += v2 * period; now = nextnow; } return NO_CLASH_TIME; } /*************************************** 弾丸も発射されるまでは停止していると見なして折れ線移動として扱う */ double read_bullet_and_calculate_clashtime(poly poly1, movelist move1){ double t, x, vx, vy, l; cin >> t >> x >> vx >> vy >> l; cd v = cd(vx, vy); line bullet = make_pair(cd(x, 0), cd(x, 0) - l * v / abs(v)); movelist move2; move2.push_back(make_pair(t, cd(0, 0))); move2.push_back(make_pair(NO_CLASH_TIME, v)); double output = NO_CLASH_TIME; for(poly::iterator it = poly1.begin(); it != poly1.end(); it++){ output = min(output, clashtime(*it, move1, bullet, move2)); } return output; } /*************************************** 多角形の読み込み */ poly read_poly(int n) { cd point[n]; for(int i = 0; i < n; i++) { double x, y; cin >> x >> y; point[i] = cd(x, y); } poly output; for(int i = 0; i < n; i++) { output.push_back(make_pair(point[i], point[(i+1)%n])); } return output; } /*************************************** 折れ線移動の読み込み */ movelist read_movelist(int n) { movelist output; for(int i = 0; i < n; i++) { double t, vx, vy; cin >> t >> vx >> vy; output.push_back(make_pair(t, cd(vx, vy))); } output.push_back(make_pair(NO_CLASH_TIME, cd(0, 0))); return output; } int main(void) { cout << setprecision(10); while(true) { int a, b, c; cin >> a >> b >> c; if(a == 0 && b == 0 && c == 0)break; poly p = read_poly(a); movelist m = read_movelist(b); vector ans; for(; c>0; c--){ double time = read_bullet_and_calculate_clashtime(p, m); if(time < NO_CLASH_TIME)ans.push_back(time); } sort(ans.begin(), ans.end()); cout << ans.size() << endl; for(vector::iterator it = ans.begin(); it != ans.end(); it++){ cout << *it << endl; } } return 0; }