Problem:
Circles and Ray

Problem

2次元平面上にそれぞれ互いに共通部分をもたない N 個の円が与えられる。
また、円にはそれぞれ1から N までの番号が割り振られている。

あなたは、端点が1番目の円の円周上にあるような半直線を任意の数だけ設置することができる。
どの円も1本以上の半直線との共通部分を持っているようにするためには、最低何本の半直線を設置しなければならないかを求めなさい。

Input

入力は以下の形式で与えられる。

N
x1 y1 r1
x2 y2 r2
...
xN yN rN

1行目に、1つの整数 N が与えられる。
2行目からの N 行のうち i 行目には i 番目の円のx座標、y座標、半径を表す3つの整数 xi, yi, ri が空白区切りで与えられる。

Constraints

2 ≤ N ≤ 16

-100 ≤ xi ≤ 100 (1 ≤ i ≤ N)

-100 ≤ yi ≤ 100 (1 ≤ i ≤ N)

1 ≤ ri ≤ 100 (1 ≤ i ≤ N)

Output

どの円も1本以上の半直線との共通部分を持っているようにするためには最低何本の半直線を設置しなければならないかを出力せよ。

Sample Input 1

3
0 0 2
3 3 1
6 1 1

Sample Output 1

1

Sample Input 2

4
1 2 3
12 2 2
7 6 2
1 9 3

Sample Output 2

2

Sample Input 3

5
0 0 5
0 10 1
10 0 1
-10 0 1
0 -10 1

Sample Output 3

4

Solution in C++11 (judge verdict: Wrong Answer)

#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define all(c) c.begin(),c.end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << x << endl
#define chmin(x,y) x=min(x,y)
#define chmax(x,y) x=max(x,y)
using namespace std;
typedef double D;
typedef complex<D> P;
typedef pair<P,P> L;
struct C{
	P p;D r;
	C(P p,D r):p(p),r(r){}
};
D eps=1e-9,PI=acos(-1);
bool eq(D a,D b){return abs(a-b)<eps;}
bool eq(P a,P b){return abs(a-b)<eps;}
int sig(D a){return eq(a,0)?0:(a>0?1:-1);}
int large(D a,D b){return eq(a,b)?0:(a>b?1:-1);}
D dot(P a,P b){return real(conj(a)*b);}
P perp(L l,P p){
	D t=dot(p-l.fs,l.fs-l.sc)/norm(l.fs-l.sc);
	return l.fs+t*(l.fs-l.sc);
}
vector<L> tanCP(C c,P p){
	int x=large(c.r,abs(p-c.p));
	vector<L> ret;
	if(x==1) return ret;
	if(x==0){
		ret.pb(L(p,p+(c.p-p)*P(0,1)));
		return ret;
	}
	D theta=acos(c.r/abs(p-c.p));
	ret.pb(L(p,c.p+(p-c.p)/abs(p-c.p)*polar(c.r,theta)));
	ret.pb(L(p,c.p+(p-c.p)/abs(p-c.p)*polar(c.r,-theta)));
	return ret;
}
vector<L> intan(C a,C b){
	P p=(a.r*b.p+b.r*a.p)/(a.r+b.r);
	return tanCP(a,p);
}
vector<L> outtan(C a,C b){
	if(eq(a.r,b.r)){
		vector<L> ret;
		P p=(a.p-b.p)/abs(a.p-b.p)*polar(a.r,PI/2);
		ret.pb(L(a.p+p,b.p+p));
		ret.pb(L(a.p-p,b.p-p));
		return ret;
	}
	P p=(a.r*b.p-b.r*a.p)/(a.r-b.r);
	return tanCP(a,p);
}
inline D dLP(L l, P p) { return abs(perp(l,p)-p);}
int iCL(C c,L l){
	D d=dLP(l,c.p);
	return eq(d,c.r)?1:(d<c.r?2:0);
}
typedef pair<P,int> Pp;
L BL;
bool compBLp(Pp &aa,Pp &bb){
	P a=aa.fs,b=bb.fs;
	return dot(BL.sc-BL.fs,a-BL.fs)<dot(BL.sc-BL.fs,b-BL.fs);
}
bool can[1<<16];
int N;
int dp[1<<16];
vector<C> cs;
vector<L> ls;
int main(){
	cin>>N;
	rep(i,N){
		int x,y,r;
		cin>>x>>y>>r;
		cs.pb(C(P(x,y),r));
	}
	rep(i,N) rep(j,i){
		vector<L> vl=intan(cs[i],cs[j]);
		ls.insert(ls.end(),all(vl));
		vl=outtan(cs[i],cs[j]);
		ls.insert(ls.end(),all(vl));
	}
	for(L l:ls){
		vector<Pp> ps;
		rep(i,N){
			if(iCL(cs[i],l)>=1) ps.pb(Pp(perp(l,cs[i].p),i));
		}
		BL=l;
		sort(all(ps),compBLp);
		int o=-1;
		int K=ps.size();
		rep(i,K) if(ps[i].sc==0) o=i;
		if(o==-1) continue;
		int x=1;
		rep(i,o) x|=(1<<ps[i].sc);
		can[x]=1;
		x=1;
		for(int i=o+1;i<K;i++) x|=(1<<ps[i].sc);
		can[x]=1;
	}
	can[0]=1;
	rep(i,N) can[1<<i]=1;
	rep(i,N){
		int j=i;
		do{
			can[j]=1;
			j=(j-1)&i;
		}while(i!=j);
	}
	rep(i,1<<N) dp[i]=1e9;
	dp[0]=0;
	rep(i,1<<N){
		int a=(1<<N)-1-i;
		int j=a;
		do{
			if(can[j]) chmin(dp[i|j],dp[i]+1);
			j=(j-1)&a;
		}while(a!=j);
	}
	cout<<dp[(1<<N)-1]<<endl;
}