Problem:
風よ、私の梅の香りを届けておくれ！

引っ越しが決まり、この地を去ることになった。この土地自体に未練は無いが、１つだけ気になることがある。それは、庭に植えた梅の木のことだ。私は毎年、この梅が花を咲かすことを楽しみにしていた。ここを離れた後は春の楽しみが１つ減ってしまう。私の梅の香りだけでも風に乗って引っ越し先の家まで届き、春を楽しませてはくれないものか。

日本には春を象徴する３つの花がある。梅・桃・桜の３つだ。引っ越し先には、私の梅以外にも、これらの花の香りが届くだろう。しかし、私の梅の香りだけが届く日数が最も多い家に住みたい。

図のように、花の香りは扇状に広がり、その領域は風の向かう方向と強さによって決まる。扇形は風の向かう方向 w を中心にして対称に広がり、風の強さ a を半径とする領域をもつ。香りが広がる角度 d は花の種類によって決まっているが、風の向かう方向と強さは日によって異なる。ただし、同じ日では、すべての場所で風の向かう方向と強さは同じである。

手元には、私の梅以外の梅・桃・桜の位置と花の種類ごとの香りが広がる角度、引っ越し先の家の候補のデータがある。さらに、数日分の風の向かう方向と強さのデータもある。私の梅以外の梅・桃・桜の木と家の位置は、私の梅の位置を原点とした座標で示されている。

これらのデータを使って、私の梅の香りだけが届く日数の最も多い家を探すためのプログラムを書いてみることとしよう。私は有能なプログラマーなのだから！

入力

入力は複数のデータセットからなる。入力の終わりはゼロ２つの行で示される。各データセットは以下の形式で与えられる。

H R
hx1 hy1
hx2 hy2
:
hxH hyH
U M S du dm ds
ux1 uy1
ux2 uy2
:
uxU uyU
mx1 my1
mx2 my2
:
mxM myM
sx1 sy1
sx2 sy2
:
sxS syS
w1 a1
w2 a2
:
wR aR

各行で与えられる数値は１つの空白で区切られている。

１行目に引っ越し先の家の候補の数 H (1 ≤ H ≤ 100) と風の記録の数 R (1 ≤ R ≤ 100) が与えられる。続くH 行に引っ越し先の家の位置が与えられる。hxi とhyiは i 番目の家の x 座標と y 座標を示す-1000 以上1000 以下の整数である。

続く１行に、私の梅以外の梅の木の数 U と、桃・桜の木の数 M、S、梅・桃・桜の香りが広がる角度du、dm、ds が与えられる。U、M、S の範囲は 0 以上10 以下である。角度の単位は度であり、1 以上180 未満の整数である。

続く U 行に私の梅以外の梅の木の位置、続く M 行に桃の木の位置、続く S 行に桜の木の位置が与えられる。uxi と uyi、mxi と myi、sxi と syi はそれぞれ、i 番目の梅・桃・桜の木の x 座標と y 座標を示す、-1000 以上 1000 以下の整数である。

続く R 行に風の記録が与えられる。wi (0 ≤ wi < 360) と ai(0 < ai ≤ 100) は i 日目の風の向かう方向と強さを表す整数である。風の向かう方向は、x 軸の正の向きから反時計回りに測った角度で表し、単位は度とする。

入力は以下の条件を満たすと考えてよい。

入力される座標はすべて異なるものとする。

原点には私の梅以外無い。

どの花についても、花の香りが届く領域の境界から距離が 0.001 以内には家は無い。

データセットの数は 50 を超えない。

出力

データセットごとに、私の梅の香りだけが届く日数の最も多い全ての家の番号を、小さい順に１行に出力する。家の番号の間は空白１つで区切る。行の終わりには空白文字を出力しない。

ただし、どの家についても、私の梅の花の香りだけが届く日が１日もなければ、NA と出力する。

入力例

6 3
2 1
1 2
5 2
1 3
1 5
-2 3
1 1 1 90 30 45
3 -4
-3 0
2 -2
45 6
90 6
135 6
2 1
1 3
5 2
0 1 1 90 30 45
-3 0
2 -2
45 6
0 0

出力例

5 6
NA

Solution in C++ (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;
typedef complex<double> Point;
typedef pair<Point, double> Tree;

int H;
Point home[100];

int U, M, S, du, dm, ds;
Tree tree[31];

int R;
int w[100], a[100];

double toRad(double theta)
{
	return theta / 180 * acos(-1);
}

double cross(Point a, Point b)
{
	return a.real() * b.imag() - a.imag() * b.real();
}

bool contains(Tree tree, Point home, double dir, double len)
{
	if (abs(home - tree.first) > len) return false;
	double left = dir + tree.second / 2;
	double right = dir - tree.second / 2;
	Point vh = home - tree.first;
	Point vl = polar(len, left);
	Point vr = polar(len, right);
	return (cross(vr, vh) > -1e-6) && (cross(vh, vl) > -1e-6);
}

void solve()
{
	// day, home
	static int reach[100][100];
	fill_n(*reach, 100 * 100, 0);
	
	for (int i = 0; i < R; i++){
		for (int j = 0; j < H; j++){
			for (int k = 0; k <= U + M + S; k++){
				if (contains(tree[k], home[j], toRad(w[i]), a[i])){
					reach[i][j] |= 1 << k;
				}
			}
		}
	}
	
	static int cnt[100];
	fill_n(cnt, 100, 0);
	
	int maxi = 0;
	for (int i = 0; i < H; i++){
		for (int j = 0; j < R; j++){
			cnt[i] += (reach[j][i] == 1);
			maxi = max(maxi, cnt[i]);
		}
	}
	
	if (maxi == 0) puts("NA");
	else {
		bool f = false;
		for (int i = 0; i < H; i++){
			if (cnt[i] == maxi){
				if (f) printf(" ");
				f = true;
				printf("%d", i + 1);
			}
		}
		puts("");
	}
}

int main()
{
	while (scanf("%d %d", &H, &R), H){
		for (int i = 0; i < H; i++){
			int x, y;
			scanf("%d %d", &x, &y);
			home[i] = Point(x, y);
		}
		
		scanf("%d %d %d", &U, &M, &S);
		scanf("%d %d %d", &du, &dm, &ds);
		tree[0] = Tree(Point(0, 0), toRad(du));
		for (int i = 0; i < U + M + S; i++){
			int x, y, d;
			scanf("%d %d", &x, &y);
			if (i < U) d = du;
			else if (i < U + M) d = dm;
			else d = ds;
			tree[i + 1] = Tree(Point(x, y), toRad(d));
		}
		
		for (int i = 0; i < R; i++){
			scanf("%d %d", &w[i], &a[i]);
		}
		
		solve();
	}
	
	return 0;
}