Problem:
Problem E: Frisbee Dogs

クレインは, 彼女の愛犬である Jack をフリスビードッグ大会に出場させようとしている. しかし, 彼女は Jack がよい成績を取れるか自信が無い. 彼女のために, 大会をシミュレートして Jack の成績を見積もるプログラムを作成してほしい.

この大会は, 2次元平面上にいる N 匹の犬によって行われる. 大会の開始時点において, i 番目の犬は (Dix, Diy) の位置にいる. i 番目の犬は Vi [m/s] で走ることができ, 全ての犬は十分小さいので点とみなせる. ある時刻に, 2 匹以上の犬が同じ位置にいても構わない.

1枚目のフリスビーの発射をもって大会は開始し, この瞬間から犬たちは動くことを許される. フリスビーもまた点とみなすことができ, i 枚目のフリスビーは (FPix, FPiy) の位置から (FVix, FViy) [m/s] の速度ベクトルで発射され, 等速直線運動を続ける. ある犬の位置とフリスビーの位置が等しくなったとき, その犬はフリスビーを取得することができる.

1枚目のフリスビーがいずれかの犬に取得された瞬間, 2枚目のフリスビーが発射される. 2枚目のフリスビーが取得された瞬間3枚目が発射され, 以下同様にフリスビーが取得された直後に次のフリスビーが発射される. M 枚目のフリスビーが取得されると大会は終了する.

言うまでもなく, 犬たちの目標はより多くのフリスビーを取得することである. 犬たちは, 以下のような戦略をとる.

フリスビーが発射されたとき, 犬は可能な限り早い時刻にそれを取得できるように移動し, フリスビーを取得する. ただし, フリスビーを取得できないときは現在いる場所に待機する.

ある犬がフリスビーを取得できるかどうかの判断は, 他の犬の行動に関係なく行われる. つまり, ある犬がフリスビーを取得するために移動したものの, 他の犬に先に取得されてしまうことも有りえる. いずれかの犬がフリスビーを取得し新たなフリスビーが発射された瞬間, 犬たちは新しいフリスビーに対して上記の戦略をとる.

あなたの作成するプログラムは、それぞれの犬が取得したフリスビーの数を出力しなければならない.

Input

入力ファイルは, 複数のデータセットから構成される.

データセットの1行目には, 犬の数 N (1 ≤ N ≤ 10) とフリスビーの数 M (1 ≤ M ≤ 1000)が与えられる.

続く N 行には, 犬の初期位置と速度 Dix, Diy, Vi が1つの空白区切りで与えられる.

続く M 行には, フリスビーの発射位置と速度 FPix, FPiy, FVix, FViy が1つの空白文字区切りで与えられる.

与えられる座標値は実数であり、その絶対値は 1000 を越えない. 与えられる速度は実数であり 1 ≤ DVi ≤ 100, -25 ≤ FVix, FViy ≤ 25 である. どの犬にも取得できないフリスビーはないと仮定してよい.

任意のフリスビーがある犬に時刻 t で取得されたとき、時刻 t + 1e-6 以前にそれを取得できる犬はいない.

シミュレーションの間, 犬の x 座標, y 座標の絶対値は 1e+8 を越えない.

N, M がともに 0 のとき入力の終わりを示す.

Output

それぞれの犬が取得したフリスビーの数を, 空白文字で区切って1行に出力せよ. 出力する順番は, 入力で与えられた順番と等しくなければならない.

Sample Input

2 1
12 5 3
0 17 3
0 0 2 2
2 3
2 0 2
100 100 2
0 0 -1 0
-2 -5 0 3
100 100 1 1
0 0

Output for the Sample Input

1 0
2 1

Solution in C# (judge verdict: Wrong Answer)

using System;
using System.Collections;
using System.Collections.Generic;
 
class TEST{
	static void Main(){
		while(true){
			//var d=Array.ConvertAll(Console.ReadLine().Split(' '),e=>int.Parse(e));
			var d=Console.ReadLine().Split(' ');
			
			if(int.Parse(d[0])==0&&int.Parse(d[1])==0)break;
			Sol mySol =new Sol(int.Parse(d[0]),int.Parse(d[1]));
			mySol.Solve();
		}
	}
}

class Sol{
	public void Solve(){
		int[] Catch=new int[N];
		for(int i=0;i<N;i++){
			Catch[i]=0;
		}

		Point[] UMove=new Point[N];
		double[] Time=new double[N];
		for(int i=0;i<M;i++){
			for(int j=0;j<N;j++){
				// |Fris+ t*FVelo - Dogs|^2 == |t*Velo|^2
				//　よりtを求める（判別式でcan/cannot catchを判定
				double A=FVelo[i].X*FVelo[i].X+FVelo[i].Y*FVelo[i].Y-Velo[j]*Velo[j];
				double B=2*(Fris[i].X-Dogs[j].X)*FVelo[i].X+2*(Fris[i].Y-Dogs[j].Y)*FVelo[i].Y;
				double C=(Fris[i].X-Dogs[j].X)*(Fris[i].X-Dogs[j].X)+(Fris[i].Y-Dogs[j].Y)*(Fris[i].Y-Dogs[j].Y);
				double D=B*B-4*A*C;
				
				if(A<=eps&&A>=-eps){
					//A=0の場合、犬とフリスビーが等速
					//　C=0（犬の位置とフリスビー位置が同じ（このケースは無い筈）
					//　B<0の時のみ解をもつ（犬とフリスビーを結ぶ線分の垂直二等分線とフリスビー軌道が交わる
					if(C<=eps&&C>=-eps){
						Time[j]=0.0;
						UMove[j]=new Point(0,0);
					}else{
						if(B>-eps){
							Time[j]=inf;
							UMove[j]=new Point(0,0);
						}else{
							Time[j]=-C/B;
							Point Ptemp1=Fris[i];
							Ptemp1=Ptemp1.Add(FVelo[i].Times(Time[j]));
							Ptemp1=Ptemp1.Add(Dogs[j].Times(-1.0));
							if(Ptemp1.Length!=0){
								UMove[j]=Ptemp1.Times(Velo[j]/Ptemp1.Length);
							}else{	UMove[j]=new Point(0,0);}
						}
					}
				}
				if(A<-eps){
					//A<0の時は必ず解があり、かつ0の両側にある
					//（A<0⇔犬の方が速い）
					//　フリスビーがアポロニウスの円に囲まれている
					Time[j]=(-B-Math.Sqrt(D))/(2.0*A);//正の解
					Point Ptemp=Fris[i];
					Ptemp=Ptemp.Add(FVelo[i].Times(Time[j]));
					Ptemp=Ptemp.Add(Dogs[j].Times(-1.0));
					if(Ptemp.Length!=0){
						UMove[j]=Ptemp.Times(Velo[j]/Ptemp.Length);
					}else{	UMove[j]=new Point(0,0);}
				}
				if(A>eps){
					//A>0の時は解がある時とない時がある						//（A<0⇔犬の方が速い）
					//　犬がアポロニウスの円に囲まれている
					//　フリスビー軌跡がT>0でアポロニウスの円と交わる時のみキャッチ可
					//　　⇔D>=0 かつ　解が正　この時、小さいほうの解を取る
					//　(解は 正,正 または 負,負　しかない）
					if(D<=-eps){
						Time[j]=inf;
						UMove[j]=new Point(0,0);
					}else{
						D+=eps;//RE避ける
						Time[j]=(-B-Math.Sqrt(D))/(2.0*A);//小さい方の符号を見ればよい
						if(Time[j]<-eps){
							Time[j]=inf;
							UMove[j]=new Point(0,0);
						}else{
							Point Ptemp=Fris[i];
							Ptemp=Ptemp.Add(FVelo[i].Times(Time[j]));
							Ptemp=Ptemp.Add(Dogs[j].Times(-1.0));
							if(Ptemp.Length!=0){
								UMove[j]=Ptemp.Times(Velo[j]/Ptemp.Length);
							}else{	UMove[j]=new Point(0,0);}
						}
					}
				}
//Console.WriteLine("dog{0}:",j);
//Console.WriteLine("A:{0,5:F2}\tB:{1,5:F2}\tC:{2,5:F2}\tD:{3,5:F2}",A,B,C,D);
//Console.WriteLine("UMove=({0,5:F2},{1,5:F2})",UMove[j].X,UMove[j].Y);
			}
			
			double Tmin=inf;
			int idx=0;
			for(int j=0;j<N;j++){
				if(Tmin>Time[j]){
					Tmin=Time[j];
					idx=j;
				}
			}
			//if(idx==-1)idx=0;
			Catch[idx]++;
			for(int j=0;j<N;j++){
				Time[j]=Tmin;
				Dogs[j]=Dogs[j].Add(UMove[j].Times(Time[j]));
			}
		}
		
		
		for(int i=0;i<N;i++){
			Console.Write(i==0?"{0}":" {0}",Catch[i]);
		}
		Console.WriteLine("");
		
		
	}

	Point[] Dogs;
	double[] Velo;
	Point[] Fris;
	Point[] FVelo;
	
	double inf;
	double eps;
	int N;
	int M;
	public Sol(int n_,int m_){
		N=n_;M=m_;
		eps=1e-9;inf=1e9;
		//eps=0.0;
		
		Dogs=new Point[N];
		Velo=new double[N];
		for(int i=0;i<N;i++){
			//var d=rda();
			var d=rsa();
			Dogs[i]=new Point(double.Parse(d[0]),double.Parse(d[1]));
			Velo[i]=double.Parse(d[2]);
		}
		
		Fris=new Point[M];
		FVelo=new Point[M];
		for(int i=0;i<M;i++){
			//var d=rda();
			var d=rsa();
			Fris[i]=new Point(double.Parse(d[0]),double.Parse(d[1]));
			FVelo[i]=new Point(double.Parse(d[2]),double.Parse(d[3]));
		}
	}

	struct Point{
		public double X;
		public double Y;
		public Point(double x_,double y_){
			X=x_;Y=y_;
		}
		public Point Times(double r){
			this.X*=r;
			this.Y*=r;
			return this;
		}
		
		public Point Add(Point q){
			this.X+=q.X;
			this.Y+=q.Y;
			return this;
		}
		public double Length{
			get{return Math.Sqrt(this.X*this.X+this.Y*this.Y);}
		}
	}
	
	
	
	
	
	
	


	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(){return Console.ReadLine().Split(' ');}
	static int[] ria(){return Array.ConvertAll(Console.ReadLine().Split(' '),e=>int.Parse(e));}
	static long[] rla(){return Array.ConvertAll(Console.ReadLine().Split(' '),e=>long.Parse(e));}
	static double[] rda(){return Array.ConvertAll(Console.ReadLine().Split(' '),e=>double.Parse(e));}
}