AOJ 1139 Earth Observation with a Mobile Robot

制約条件

入力は全て整数
n≦100

方針

ロボット同士の距離がRになるタイミングを全部列挙する。
そのタイミングでのデータの遷移を全部シミュレーションすればいい。


ロボット同士の距離がRになるタイミングは、
時間tにおけるそれぞれの折れ線上でのロボットの座標が、
(x0 + vx(t - t0), y0 + vy(t - t0))とかけることから、
ロボット同士の距離=Rという式はtに関する二次方程式になって、それを解けば出てくる。


線分同士を全部見るとさすがに間に合わないので、
尺取法で、必要な線分同士だけを見るようにする。


データの遷移は、union-findか何かを使って適当にマージすればいい。
割とやるだけ。

ソースコード

const int MX = 1010, SZ = 110;
ll n, T, r, x[SZ], y[SZ], sz[SZ], px[SZ][MX], py[SZ][MX];
ll t[SZ][MX], vx[SZ][MX], vy[SZ][MX];
string name[SZ];
double xs[SZ], ys[SZ];
bool ok[SZ];
int p[SZ];
inline int root(int x){ return x == p[x] ? x : (p[x] = root(p[x])); }

inline pair<double, double> solve(double a, double b, double c){
	if(a == 0){
		if(b == 0) return mp(INF, INF);
		return mp(-c / b, INF);
	}
	double D = b * b - 4 * a * c;
	if(D < 0) return mp(INF, INF);
	D = sqrt(D);
	return mp((-b + D) / (2 * a), (-b - D) / (2 * a));
}
inline double dist(double x, double y){
	return sqrt(x * x + y * y);
}

int main()
{
	while(1){
		cin >> n >> T >> r;
		if(n == 0) break;
		set<double> ts;
		rep(i, n){
			cin >> name[i];
			int k = 0;
			while(cin >> t[i][k] >> vx[i][k] >> vy[i][k]){
				ts.insert(t[i][k]);
				px[i][k] = k ? px[i][k - 1] + ll(t[i][k] - t[i][k - 1]) * vx[i][k] : vx[i][k];
				py[i][k] = k ? py[i][k - 1] + ll(t[i][k] - t[i][k - 1]) * vy[i][k] : vy[i][k];
				if(t[i][k++] == T) break;
			}
			sz[i] = k;
		}
		
		rep(i, n) rep(j, i){
			for(int a = 0, b = 0; a < sz[i] - 1 && b < sz[j] - 1; a++){
				while(b < sz[j] - 1 && t[i][a] > t[j][b + 1]) b++;
				for(; b < sz[j] - 1 && t[j][b] <= t[i][a + 1]; b++){
					double xa = px[i][a], ya = py[i][a], vxa = vx[i][a + 1], vya = vy[i][a + 1];
					double xb = px[j][b], yb = py[j][b], vxb = vx[j][b + 1], vyb = vy[j][b + 1];
					double dvx = vxa - vxb, dvy = vya - vyb;
					double dx = xa - xb - vxa * t[i][a] + vxb * t[j][b];
					double dy = ya - yb - vya * t[i][a] + vyb * t[j][b];
					pair<double, double> p = solve(dvx * dvx + dvy * dvy,
						2 * dvx * dx + 2 * dvy * dy, dx * dx + dy * dy - r * r);
					if(max(t[i][a], t[j][b]) - EPS < p.first  &&
						p.first  < min(t[i][a + 1], t[j][b + 1]) + EPS)
						ts.insert(p.first);
					if(max(t[i][a], t[j][b]) - EPS < p.second &&
						p.second < min(t[i][a + 1], t[j][b + 1]) + EPS)
						ts.insert(p.second);
					if(b + 1 == sz[j] - 1 || t[j][b + 1] > t[i][a + 1]) break;
				}
			}
		}
		memset(ok, 0, sizeof(ok));
		ok[0] = 1;
		fr(it, ts){
			double T = *it;
			
			rep(i, n){
				int j = lower_bound(t[i], t[i] + sz[i], T + EPS) - t[i] - 1;
				xs[i] = px[i][j] + vx[i][j + 1] * (T - t[i][j]);
				ys[i] = py[i][j] + vy[i][j + 1] * (T - t[i][j]);
			}
			
			rep(i, n) p[i] = i;
			rep(i, n) rep(j, i){
				if(dist(xs[i] - xs[j], ys[i] - ys[j]) < r + EPS){
					int a = root(i), b = root(j);
					if(a != b) p[a] = b;
				}
			}
			rep(i, n) if(ok[i]) rep(j, n) if(root(i) == root(j)) ok[j] = 1;
		}
		set<string> ans;
		rep(i, n) if(ok[i]) ans.insert(name[i]);
		fr(i, ans) cout << *i << endl;
	}
	return 0;
}