Problem:
Circles and Ray
Problem
2次元平面上にそれぞれ互いに共通部分をもたない
N
個の円が与えられる。
また、円にはそれぞれ1から
N
までの番号が割り振られている。
あなたは、端点が1番目の円の円周上にあるような半直線を任意の数だけ設置することができる。
どの円も1本以上の半直線との共通部分を持っているようにするためには、最低何本の半直線を設置しなければならないかを求めなさい。
Input
入力は以下の形式で与えられる。
N
x
1
y
1
r
1
x
2
y
2
r
2
...
x
N
y
N
r
N
1行目に、1つの整数
N
が与えられる。
2行目からの
N
行のうち
i
行目には
i
番目の円のx座標、y座標、半径を表す3つの整数
x
i
, y
i
, r
i
が空白区切りで与えられる。
Constraints
2 ≤
N
≤ 16
-100 ≤
x
i
≤ 100 (1 ≤
i
≤
N
)
-100 ≤
y
i
≤ 100 (1 ≤
i
≤
N
)
1 ≤
r
i
≤ 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

Submitted solutions:

code_snippet: // AOJ #1582 Circles and Ray
// 2025.2.23

#include <bits/stdc++.h>
using namespace std;

const double EPS = 1e-9;
const double PI = acos(-1.0);

struct Circle { int x, y, r; };

struct RayCandidate {
    double px, py;
    double dx, dy;
    int mask;
};

double dist(double ax, double ay, double bx, double by) {
    return hypot(ax - bx, ay - by);
}

double normAngle(double a) {
    while(a < 0) a += 2*PI;
    while(a >= 2*PI) a -= 2*PI;
    return a;
}

bool hitCircle(double Px, double Py, double dx, double dy, double cx, double cy, double r) {
    double vx = cx - Px, vy = cy - Py;
    double t = vx * dx + vy * dy;
    if(t < 0) return false;
    double projx = Px + t * dx, projy = Py + t * dy;
    return (dist(projx, projy, cx, cy) <= r + EPS);
}

int solveDP(const vector<RayCandidate>& rays, int N) {
    int full = (1 << N) - 1;
    vector<int> dp(1 << N, 1e9);
    dp[0] = 0;
    for (int mask = 0; mask < (1 << N); mask++) {
        if(dp[mask] == 1e9) continue;
        for(auto &ray : rays) {
            int nmask = mask | ray.mask;
            dp[nmask] = min(dp[nmask], dp[mask] + 1);
        }
    }
    return dp[full];
}

void addCandidateFromCircle1(const Circle &c1, const Circle &c2, vector<RayCandidate> &rays) {
    double cx1 = c1.x, cy1 = c1.y, r1 = c1.r;
    double cx2 = c2.x, cy2 = c2.y, r2 = c2.r;
    double d = dist(cx1, cy1, cx2, cy2);
    double base = atan2(cy2 - cy1, cx2 - cx1);
    if(d + EPS >= fabs(r1 - r2)) {
        double diff = (r1 - r2) / d;
        if(diff > 1) diff = 1; if(diff < -1) diff = -1;
        double ang = acos(diff);
        for (int sign = -1; sign <= 1; sign += 2) {
            double theta = normAngle(base + sign * ang);
            double Px = cx1 + r1 * cos(theta);
            double Py = cy1 + r1 * sin(theta);
            double dx = -sin(theta), dy = cos(theta);
            double dot = (cx2 - Px)*dx + (cy2 - Py)*dy;
            if(dot < 0) { dx = -dx; dy = -dy; }
            RayCandidate ray;
            ray.px = Px; ray.py = Py; ray.dx = dx; ray.dy = dy;
            rays.push_back(ray);
        }
    }
    if(d + EPS >= r1 + r2) {
        double diff = (r1 + r2) / d;
        if(diff > 1) diff = 1; if(diff < -1) diff = -1;
        double ang = acos(diff);
        for (int sign = -1; sign <= 1; sign += 2) {
            double theta = normAngle(base + sign * ang);
            double Px = cx1 + r1 * cos(theta);
            double Py = cy1 + r1 * sin(theta);
            double dx = -sin(theta), dy = cos(theta);
            double dot = (cx2 - Px)*dx + (cy2 - Py)*dy;
            if(dot < 0) { dx = -dx; dy = -dy; }
            RayCandidate ray;
            ray.px = Px; ray.py = Py; ray.dx = dx; ray.dy = dy;
            rays.push_back(ray);
        }
    }
}

void addCandidateFromPair(const Circle &c1, const Circle &ci, const Circle &cj, vector<RayCandidate> &rays) {
    double xi = ci.x, yi = ci.y, ri = ci.r;
    double xj = cj.x, yj = cj.y, rj = cj.r;
    double d = dist(xi, yi, xj, yj);
    for (int s_i = -1; s_i <= 1; s_i += 2) {
        for (int s_j = -1; s_j <= 1; s_j += 2) {
            double diff = ri * s_i - rj * s_j;
            if(d + EPS < fabs(diff)) continue;
            double cosVal = diff / d;
            if(cosVal > 1) cosVal = 1; if(cosVal < -1) cosVal = -1;
            double angOff = acos(cosVal);
            double base = atan2(yj - yi, xj - xi);
            for (int sign = -1; sign <= 1; sign += 2) {
                double theta = normAngle(base + sign * angOff);
                double Pi_x = xi + s_i * ri * cos(theta);
                double Pi_y = yi + s_i * ri * sin(theta);
                double ax = -s_i * sin(theta), ay = s_i * cos(theta);
                double cx1 = c1.x, cy1 = c1.y, r1 = c1.r;
                double Bx = Pi_x - cx1, By = Pi_y - cy1;
                double A_dot_B = ax * Bx + ay * By;
                double B2 = Bx*Bx + By*By;
                double disc = A_dot_B*A_dot_B - (B2 - r1*r1);
                if(disc < -EPS) continue;
                disc = max(disc, 0.0);
                double t1 = -A_dot_B + sqrt(disc);
                double t2 = -A_dot_B - sqrt(disc);
                for(double t : {t1, t2}) {
                    double X = Pi_x + t * ax, Y = Pi_y + t * ay;
                    if(fabs(dist(X, Y, cx1, cy1) - r1) > 1e-6) continue;
                    double dot = (Pi_x - X)*ax + (Pi_y - Y)*ay;
                    double useAx = ax, useAy = ay;
                    if(dot < -EPS) {
                        dot = (Pi_x - X)*(-ax) + (Pi_y - Y)*(-ay);
                        useAx = -ax; useAy = -ay;
                    }
                    if(dot < -EPS) continue;
                    RayCandidate ray;
                    ray.px = X; ray.py = Y; ray.dx = useAx; ray.dy = useAy;
                    rays.push_back(ray);
                }
            }
        }
    }
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int N;
    cin >> N;
    vector<Circle> circ(N);
    for (int i = 0; i < N; i++){
        cin >> circ[i].x >> circ[i].y >> circ[i].r;
    }

    vector<RayCandidate> rays;
    for (int i = 1; i < N; i++){
        addCandidateFromCircle1(circ[0], circ[i], rays);
    }
    for (int i = 1; i < N; i++){
        for (int j = i + 1; j < N; j++){
            addCandidateFromPair(circ[0], circ[i], circ[j], rays);
        }
    }

    for(auto &ray : rays) {
        int m = 0;
        for (int i = 0; i < N; i++){
            if(hitCircle(ray.px, ray.py, ray.dx, ray.dy, circ[i].x, circ[i].y, circ[i].r))
                m |= (1 << i);
        }
        ray.mask = m;
    }
    int ans = solveDP(rays, N);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 4068
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}
 
/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)
 
// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}
 
// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}
 
// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}
 
// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}
 
VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}
 
// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  bool change = false;
  if(ar > br){
    swap(ar,br);
    swap(a,b);
    change = true;
  }
  double PI = acos(-1);
  vector<Line> ls;
  double d = abs(b-a);
  assert(!EQ(ar+br,d));
  double y = br-ar;
  double theta = asin(y/d);
  double phi = arg(b-a);
  for(int sign : {-1,1}){
    ls.push_back(Line(
      a+polar(ar,phi+sign*(theta+PI/2)), 
      b+polar(br,phi+sign*(theta+PI/2))));
  }
  y = br+ar;
  theta = asin(y/d);
  phi = arg(b-a);
  for(int sign : {-1,1}){
    ls.push_back(Line(
      a+polar(ar,phi+sign*(theta-PI/2)), 
      b+polar(br,phi+sign*(theta-PI/2)+PI)));
  }
  if(change)rep(i,ls.size()) {
    Point p,q;
    p = ls[i].first;
    q = ls[i].second;
    ls[i] = {q,p};
  }

  // rep (i,2) {
  //   double sin = (ar - (1-i*2)*br) / d;
  //   if (!LE(sin*sin, 1)) break;
  //   double cos = sqrt(max(1 - sin*sin, 0.0));
  //   rep (j,2) {
  //     Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
  //     assert(EQ(abs(n),1.0));
  //     ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
  //     if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
  //   }
  // }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];
 
int main(){
    int n;
    cin >>n;
 
    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }
 
    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[j],r[j],c[i],r[i]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;
 
            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;
 
            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;
 
                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }
 
            m[i][j][k] = m[j][i][k] = val;
        }
    }
 
    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }
 
    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 0.3103448275862069
time_ms: 60
memory_kb: 3784
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}
 
/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)
 
// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}
 
// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}
 
// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}
 
// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}
 
VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}
 
// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  bool change = false;
  if(ar > br){
    swap(ar,br);
    swap(a,b);
    change = true;
  }
  double PI = acos(-1);
  vector<Line> ls;
  double d = abs(b-a);
  assert(!EQ(ar+br,d));
  double y = br-ar;
  double theta = asin(y/d);
  double phi = arg(b-a);
  for(int sign : {-1,1}){
    ls.push_back(Line(
      a+polar(ar,phi+sign*(theta+PI/2)), 
      b+polar(br,phi+sign*(theta+PI/2))));
  }
  y = br+ar;
  theta = asin(y/d);
  phi = arg(b-a);
  for(int sign : {-1,1}){
    ls.push_back(Line(
      a+polar(ar,phi+sign*(theta-PI/2)), 
      b+polar(br,phi+sign*(theta-PI/2)+PI)));
  }
  if(change)rep(i,ls.size()) {
    Point p,q;
    p = ls[i].first;
    q = ls[i].second;
    ls[i] = {q,p};
  }

  // rep (i,2) {
  //   double sin = (ar - (1-i*2)*br) / d;
  //   if (!LE(sin*sin, 1)) break;
  //   double cos = sqrt(max(1 - sin*sin, 0.0));
  //   rep (j,2) {
  //     Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
  //     assert(EQ(abs(n),1.0));
  //     ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
  //     if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
  //   }
  // }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];
 
int main(){
    int n;
    cin >>n;
 
    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }
 
    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;
 
            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;
 
            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;
 
                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }
 
            m[i][j][k] = m[j][i][k] = val;
        }
    }
 
    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }
 
    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 3840
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}
 
/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)
 
// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}
 
// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}
 
// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}
 
// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}
 
VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}
 
// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  bool change = false;
  if(ar > br){
    swap(ar,br);
    swap(a,b);
    change = true;
  }
  double PI = acos(-1);
  vector<Line> ls;
  double d = abs(b-a);
  assert(!EQ(ar+br,d));
  double y = br-ar;
  double theta = asin(y/d);
  double phi = arg(b-a);
  for(int sign : {-1,1}){
    ls.push_back(Line(
      a+polar(ar,phi+sign*(theta+PI/2)), 
      b+polar(br,phi+sign*(theta+PI/2))));
  }
  y = br+ar;
  theta = asin(y/d);
  phi = arg(b-a);
  for(int sign : {-1,1}){
    ls.push_back(Line(
      a+polar(ar,phi+sign*(theta-PI/2)), 
      b+polar(br,phi+sign*(theta-PI/2)+PI)));
  }
  if(change)for(auto l : ls) {
    swap(l.first,l.second);
  }

  // rep (i,2) {
  //   double sin = (ar - (1-i*2)*br) / d;
  //   if (!LE(sin*sin, 1)) break;
  //   double cos = sqrt(max(1 - sin*sin, 0.0));
  //   rep (j,2) {
  //     Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
  //     assert(EQ(abs(n),1.0));
  //     ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
  //     if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
  //   }
  // }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];
 
int main(){
    int n;
    cin >>n;
 
    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }
 
    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;
 
            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;
 
            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;
 
                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }
 
            m[i][j][k] = m[j][i][k] = val;
        }
    }
 
    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }
 
    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 0.3103448275862069
time_ms: 60
memory_kb: 3844
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}
 
/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)
 
// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}
 
// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}
 
// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}
 
// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}
 
VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}
 
// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  vector<Line> ls;
  double d = abs(b-a);
  rep (i,2) {
    double sin = (ar - (1-i*2)*br) / d;
    if (!LE(sin*sin, 1)) break;
    double cos = sqrt(max(1 - sin*sin, 0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}
 
const int N = 16;
int dp[1<<N];
int m[N][N][4];
 
int main(){
    int n;
    cin >>n;
 
    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }
    reverse(all(c));
    reverse(all(r));
    swap(c[0],c[n-1]);
    swap(r[0],r[n-1]);
 
    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;
 
            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;
 
            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;
 
                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }
 
            m[i][j][k] = m[j][i][k] = val;
        }
    }
 
    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }
 
    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 3428
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}
 
/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)
 
// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}
 
// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}
 
// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}
 
// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}
 
VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}
 
// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  if(ar > br){
    swap(ar,br);
    swap(a,b);
  }
  double PI = acos(-1);
  vector<Line> ls;
  double d = abs(b-a);
  assert(!EQ(ar+br,d));
  double y = br-ar;
  double theta = asin(y/d);
  double phi = arg(b-a);
  for(int sign : {-1,1}){
    ls.push_back(Line(
      a+polar(ar,phi+sign*(theta+PI/2)), 
      b+polar(br,phi+sign*(theta+PI/2))));
  }
  y = br+ar;
  theta = asin(y/d);
  phi = arg(b-a);
  for(int sign : {-1,1}){
    ls.push_back(Line(
      a+polar(ar,phi+sign*(theta-PI/2)), 
      b+polar(br,phi+sign*(theta-PI/2)+PI)));
  }

  // rep (i,2) {
  //   double sin = (ar - (1-i*2)*br) / d;
  //   if (!LE(sin*sin, 1)) break;
  //   double cos = sqrt(max(1 - sin*sin, 0.0));
  //   rep (j,2) {
  //     Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
  //     assert(EQ(abs(n),1.0));
  //     ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
  //     if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
  //   }
  // }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];
 
int main(){
    int n;
    cin >>n;
 
    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }
 
    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;
 
            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;
 
            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;
 
                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }
 
            m[i][j][k] = m[j][i][k] = val;
        }
    }
 
    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }
 
    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 0.3103448275862069
time_ms: 60
memory_kb: 3840
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}
 
/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)
 
// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}
 
// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}
 
// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}
 
// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}
 
VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}
 
// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  if(ar > br){
    swap(ar,br);
    swap(a,b);
  }
  double PI = acos(-1);
  vector<Line> ls;
  double d = abs(b-a);
  double y = br-ar;
  double theta = asin(y/d);
  double phi = arg(b-a);
  for(int sign : {-1,1}){
    ls.push_back(Line(
      a+polar(ar,phi+sign*(theta+PI/2)), 
      b+polar(br,phi+sign*(theta+PI/2))));
  }
  y = br+ar;
  theta = asin(y/d);
  phi = arg(b-a);
  for(int sign : {-1,1}){
    ls.push_back(Line(
      a+polar(ar,phi+sign*(theta-PI/2)), 
      b+polar(br,phi+sign*(theta-PI/2)+PI)));
  }

  // rep (i,2) {
  //   double sin = (ar - (1-i*2)*br) / d;
  //   if (!LE(sin*sin, 1)) break;
  //   double cos = sqrt(max(1 - sin*sin, 0.0));
  //   rep (j,2) {
  //     Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
  //     assert(EQ(abs(n),1.0));
  //     ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
  //     if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
  //   }
  // }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];
 
int main(){
    int n;
    cin >>n;
 
    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }
 
    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;
 
            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;
 
            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;
 
                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }
 
            m[i][j][k] = m[j][i][k] = val;
        }
    }
 
    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }
 
    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 0.3103448275862069
time_ms: 60
memory_kb: 3844
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}
 
/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
const double PI = acos(-1);
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)
 
// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}
 
// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}
 
// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}
 
// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}
 
VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}
 
// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  if(ar > br){
    swap(ar,br);
    swap(a,b);
  }

  vector<Line> ls;
  double d = abs(b-a);
  double y = br-ar;
  double theta = asin(y/d);
  double phi = arg(b-a);
  for(int sign : {-1,1}){
    ls.push_back(
      Line(a+polar(ar,phi+sign*(theta+PI/2)), 
           b+polar(br,phi+sign*(theta+PI/2))));
  }
  y = br+ar;
  theta = asin(y/d);
  phi = arg(b-a);
  for(int sign : {-1,1}){
    ls.push_back(Line(
      a+polar(ar,phi+sign*(theta-PI/2)), 
      b+polar(br,phi+sign*(theta-PI/2)+PI)));
  }

  // rep (i,2) {
  //   double sin = (ar - (1-i*2)*br) / d;
  //   if (!LE(sin*sin, 1)) break;
  //   double cos = sqrt(max(1 - sin*sin, 0.0));
  //   rep (j,2) {
  //     Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
  //     assert(EQ(abs(n),1.0));
  //     ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
  //     if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
  //   }
  // }
  return ls;
}
 
const int N = 16;
int dp[1<<N];
int m[N][N][4];
 
int main(){
    int n;
    cin >>n;
 
    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }
 
    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;
 
            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;
 
            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;
 
                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }
 
            m[i][j][k] = m[j][i][k] = val;
        }
    }
 
    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }
 
    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 0.3103448275862069
time_ms: 60
memory_kb: 3832
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}
 
/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)
 
// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}
 
// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}
 
// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}
 
// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}
 
VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}
 
// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  vector<Line> ls;
  double d = abs(b-a);
  if(ar < br){
    swap(ar,br);
    swap(a,b);
  }
  rep (i,2) {
    double sin = (ar - (1-i*2)*br) / d;
    if (!LE(sin*sin, 1)) break;
    double cos = sqrt(max(1 - sin*sin, 0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      assert(EQ(abs(n),1.0));
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}
 
const int N = 16;
int dp[1<<N];
int m[N][N][4];
 
int main(){
    int n;
    cin >>n;
 
    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }
 
    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[j],r[j],c[i],r[i]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;
 
            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;
 
            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;
 
                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }
 
            m[i][j][k] = m[j][i][k] = val;
        }
    }
 
    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }
 
    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 0.3103448275862069
time_ms: 60
memory_kb: 3408
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}
 
/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)
 
// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}
 
// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}
 
// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}
 
// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}
 
VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}
 
// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  vector<Line> ls;
  double d = abs(b-a);
  rep (i,2) {
    double sin = (ar - (1-i*2)*br) / d;
    if (!LE(sin*sin, 1)) break;
    double cos = sqrt(max(1 - sin*sin, 0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      assert(EQ(abs(n),1.0));
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}
 
const int N = 16;
int dp[1<<N];
int m[N][N][4];
 
int main(){
    int n;
    cin >>n;
 
    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }
 
    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[j],r[j],c[i],r[i]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;
 
            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;
 
            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;
 
                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }
 
            m[i][j][k] = m[j][i][k] = val;
        }
    }
 
    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }
 
    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 0.3103448275862069
time_ms: 60
memory_kb: 3424
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}
 
/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)
 
// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}
 
// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}
 
// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}
 
// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}
 
VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}
 
// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  vector<Line> ls;
  double d = abs(b-a);
  rep (i,2) {
    double sin = (ar - (1-i*2)*br) / d;
    if (EQ(sin*sin, 1)) break;
    double cos = sqrt(max(1 - sin*sin, 0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}
 
const int N = 16;
int dp[1<<N];
int m[N][N][4];
 
int main(){
    int n;
    cin >>n;
 
    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }
 
    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[j],r[j],c[i],r[i]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;
 
            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;
 
            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;
 
                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }
 
            m[i][j][k] = m[j][i][k] = val;
        }
    }
 
    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }
 
    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 0.3103448275862069
time_ms: 60
memory_kb: 3420
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)

// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}

// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}

// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}

// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}

VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}

// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  vector<Line> ls;
  double d = abs(b-a);
  rep (i,2) {
    double sin = (ar - (1-i*2)*br) / d;
    if (!LE(sin*sin, 1)) break;
    double cos = sqrt(max(1 - sin*sin, 0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];

int main(){
    int n;
    cin >>n;

    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }

    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;

            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;

            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;

                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }

            m[i][j][k] = m[j][i][k] = val;
        }
    }

    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }

    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 3420
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)

// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}

// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}

// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}

// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}

VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}

// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  vector<Line> ls;
  double d = abs(b-a);
  rep (i,2) {
    double sin = (ar - (1-i*2)*br) / d;
    if (!LE(sin*sin, 1)) break;
    double cos = sqrt(max(1 - sin*sin, 0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];

int main(){
    int n;
    cin >>n;

    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }

    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[j],r[j],c[i],r[i]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;

            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;

            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;

                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }

            m[i][j][k] = m[j][i][k] = val;
        }
    }

    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }

    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 0.3103448275862069
time_ms: 60
memory_kb: 3408
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)

// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}

// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}

// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}

// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}

VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}

// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  vector<Line> ls;
  double d = abs(b-a);
  rep (i,2) {
    double sin = (ar - (1-i*2)*br) / d;
    if (!LE(sin*sin, 1)) break;
    double cos = sqrt(max(1 - sin*sin, 0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];

int main(){
    int n;
    cin >>n;

    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }

    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;

            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;

            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;

                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }

            m[i][j][k] = m[j][i][k] = val;
        }
    }

    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,i)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }

    cout << dp[(1<<n)-1] << endl;
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3428
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

/* 基本要素 */
typedef complex<long double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)

// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}

// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}

// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}

// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}

double distLP(Point a1, Point a2, Point p) {
  return abs(proj(a1, a2, p) - p);
}

double distLC(Point a1, Point a2, Point c, double r) {
  return max(distLP(a1, a2, c) - r, 0.0);
}

VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), (long double)0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}

// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, long double ar, Point b, long double br) {
  vector<Line> ls;
  long double d = abs(b-a);
  rep (i,2) {
    long double sin = (ar - (1-i*2)*br) / d;
    if (!LE(sin*sin, 1)) break;
    long double cos = sqrt(max(1 - sin*sin, (long double)0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];

int main(){
    int n;
    cin >>n;

    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }

    rep(i,n)rep(j,i)if(i!=j){
        vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);

        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;

            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;

            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;

                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }

            m[i][j][k] = val;
        }
    }

    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,i)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }

    int ans = dp[(1<<n)-1];
    assert(ans<n);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3428
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)

// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}

// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}

// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}

// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}

double distLP(Point a1, Point a2, Point p) {
  return abs(proj(a1, a2, p) - p);
}

double distLC(Point a1, Point a2, Point c, double r) {
  return max(distLP(a1, a2, c) - r, 0.0);
}

VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}

// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  vector<Line> ls;
  double d = abs(b-a);
  rep (i,2) {
    double sin = (ar - (1-i*2)*br) / d;
    if (!LE(sin*sin, 1)) break;
    double cos = sqrt(max(1 - sin*sin, 0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];

int main(){
    int n;
    cin >>n;

    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }

    rep(i,n)rep(j,n)if(i!=j){
        vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);

        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;

            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;

            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;

                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }

            m[i][j][k] = val;
        }
    }

    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }

    int ans = dp[(1<<n)-1];
    assert(ans<n);
    cout << ans << endl;
    return 0;
}
accuracy: 0.3103448275862069
time_ms: 60
memory_kb: 3428
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)

// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}

// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}

// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}

// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}

double distLP(Point a1, Point a2, Point p) {
  return abs(proj(a1, a2, p) - p);
}

double distLC(Point a1, Point a2, Point c, double r) {
  return max(distLP(a1, a2, c) - r, 0.0);
}

VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}

// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  vector<Line> ls;
  double d = abs(b-a);
  rep (i,2) {
    double sin = (ar - (1-i*2)*br) / d;
    if (!LE(sin*sin, 1.0)) break;
    double cos = sqrt(max(1 - sin*sin, 0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];

int main(){
    int n;
    cin >>n;

    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }

    rep(i,n)rep(j,i){
        // vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);
        vector<Line> seg = tangentLines(c[j],r[j],c[i],r[i]);

        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;

            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;

            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;

                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }

            m[i][j][k] = m[j][i][k] = val;
        }
    }

    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,i)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }

    int ans = dp[(1<<n)-1];
    assert(ans<n);
    cout << ans << endl;
    return 0;
}
accuracy: 0.3103448275862069
time_ms: 30
memory_kb: 3428
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)

// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}

// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}

// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}

// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}

double distLP(Point a1, Point a2, Point p) {
  return abs(proj(a1, a2, p) - p);
}

double distLC(Point a1, Point a2, Point c, double r) {
  return max(distLP(a1, a2, c) - r, 0.0);
}

VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}

// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  vector<Line> ls;
  double d = abs(b-a);
  rep (i,2) {
    double sin = (ar - (1-i*2)*br) / d;
    if (!LE(sin*sin, 1)) break;
    double cos = sqrt(max(1 - sin*sin, 0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];

int main(){
    int n;
    cin >>n;

    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }

    rep(i,n)rep(j,i){
        // vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);
        vector<Line> seg = tangentLines(c[j],r[j],c[i],r[i]);

        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);
            if(tmp.size()==0) continue;

            Point p = tmp[0];
            if(ccw(p,l.fi,l.se)==2) continue;

            int val = (1<<i)|(1<<j)|1;
            for(int x=1; x<n; ++x)if(x!=i && x!=j){
                VP ump = crosspointLC(p,l.fi,c[x],r[x]);
                if(ump.size()==0) continue;

                Point cc = ump[0];
                if(ccw(p,l.fi,cc)!=2) val |= (1<<x);
            }

            m[i][j][k] = m[j][i][k] = val;
        }
    }

    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,i)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }

    int ans = dp[(1<<n)-1];
    assert(ans<n);
    cout << ans << endl;
    return 0;
}
accuracy: 0.3103448275862069
time_ms: 30
memory_kb: 3408
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)

// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}

// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}

// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}

// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}

double distLP(Point a1, Point a2, Point p) {
  return abs(proj(a1, a2, p) - p);
}

double distLC(Point a1, Point a2, Point c, double r) {
  return max(distLP(a1, a2, c) - r, 0.0);
}

VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}

// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  vector<Line> ls;
  double d = abs(b-a);
  rep (i,2) {
    double sin = (ar - (1-i*2)*br) / d;
    if (!LE(sin*sin, 1)) break;
    double cos = sqrt(max(1 - sin*sin, 0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];

int main(){
    int n;
    cin >>n;

    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }

    rep(j,n)rep(i,j){
        vector<Line> seg = tangentLines(c[j],r[j],c[i],r[i]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);

            if(tmp.size()>0){
                Point p = tmp[0];
                Point q = l.fi;
                if(ccw(p,q,l.se)==2) continue;

                int val = (1<<i)|(1<<j);
                rep(x,n)if(x!=i && x!=j){
                    VP ump = crosspointLC(p,q,c[x],r[x]);
                    if(ump.size()>0){
                        // dbg(crosspointLC(p,q,c[x],r[x]).size());

                        Point cc = ump[0];
                        if(ccw(p,q,cc)!=2) val |= (1<<x);
                    }
                }

                assert((val&1) == 1);
                m[i][j][k] = m[j][i][k] = val;
            }
        }
    }

    // rep(i,n)rep(j,n)rep(k,4){
    //     printf(" %d %d %d  -> %d\n", i,j,k,m[i][j][k]);
    // }

    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,n)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }

    int ans = dp[(1<<n)-1];
    assert(ans<n);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 3408
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

/* 基本要素 */
typedef complex<double> Point;
typedef pair<Point, Point> Line;
typedef vector<Point> VP;
const double EPS = 1e-6; // 許容誤差^2
const double INF = 1e9;
#define X real()
#define Y imag()
// #define LE(n,m) ((n) < (m) + EPS)
#define LE(n,m) ((n) - (m) < EPS)
// #define GE(n,m) ((n) + EPS > (m))
#define GE(n,m) (EPS > (m) - (n))
#define EQ(n,m) (abs((n)-(m)) < EPS)

// 内積　dot(a,b) = |a||b|cosθ
double dot(Point a, Point b) {
  return a.X*b.X + a.Y*b.Y;
}

// 外積　cross(a,b) = |a||b|sinθ
double cross(Point a, Point b) {
  return a.X*b.Y - a.Y*b.X;
}

// 点の進行方向
int ccw(Point a, Point b, Point c) {
  b -= a;  c -= a;
  if (cross(b,c) >  EPS) return +1;  // counter clockwise
  if (cross(b,c) < -EPS) return -1;  // clockwise
  if (dot(b,c)   < -EPS) return +2;  // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
  return 0;                          // a--c--b on line or a==c or b==c
}

// 点pの直線aへの射影点を返す
Point proj(Point a1, Point a2, Point p) {
  return a1 + dot(a2-a1, p-a1)/norm(a2-a1) * (a2-a1);
}

double distLP(Point a1, Point a2, Point p) {
  return abs(proj(a1, a2, p) - p);
}

double distLC(Point a1, Point a2, Point c, double r) {
  return max(distLP(a1, a2, c) - r, 0.0);
}

VP crosspointLC(Point a1, Point a2, Point c, double r) {
  VP ps;
  Point ft = proj(a1, a2, c);
  if(!GE(r*r,norm(ft-c))) return ps;
  Point dir = sqrt(max(r*r - norm(ft-c), 0.0)) / abs(a2-a1) * (a2-a1);
  ps.push_back(ft + dir);
  if (!EQ(r*r, norm(ft-c))) ps.push_back(ft - dir);
  return ps;
}

// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<Line> tangentLines(Point a, double ar, Point b, double br) {
  vector<Line> ls;
  double d = abs(b-a);
  rep (i,2) {
    double sin = (ar - (1-i*2)*br) / d;
    if (!LE(sin*sin, 1)) break;
    double cos = sqrt(max(1 - sin*sin, 0.0));
    rep (j,2) {
      Point n = (b-a) * Point(sin, (1-j*2)*cos) / d;
      ls.push_back(Line(a + ar*n, b + (1-i*2)*br*n));
      if (cos < EPS) break;  // 重複する接線を無視（重複していいならこの行不要）
    }
  }
  return ls;
}

const int N = 16;
int dp[1<<N];
int m[N][N][4];

int main(){
    int n;
    cin >>n;

    vector<Point> c(n);
    vector<int> r(n);
    rep(i,n){
        int x,y;
        cin >>x >>y >>r[i];
        c[i] = Point(x,y);
    }

    rep(i,n)rep(j,i){
        vector<Line> seg = tangentLines(c[i],r[i],c[j],r[j]);
        int S = seg.size();
        assert(S==4);
        rep(k,S){
            Line l = seg[k];
            VP tmp = crosspointLC(l.fi,l.se,c[0],r[0]);

            if(tmp.size()>0){
                Point p = tmp[0];
                Point q = l.fi;
                if(ccw(p,q,l.se)==2) continue;

                int val = (1<<i)|(1<<j);
                rep(x,n)if(x!=i && x!=j){
                    VP ump = crosspointLC(p,q,c[x],r[x]);
                    if(ump.size()>0){
                        // dbg(crosspointLC(p,q,c[x],r[x]).size());

                        Point cc = ump[0];
                        if(ccw(p,q,cc)!=2) val |= (1<<x);
                    }
                }

                assert((val&1) == 1);
                m[i][j][k] = m[j][i][k] = val;
            }
        }
    }

    // rep(i,n)rep(j,n)rep(k,4){
    //     printf(" %d %d %d  -> %d\n", i,j,k,m[i][j][k]);
    // }

    fill(dp,dp+(1<<N),10101);
    dp[1] = 0;
    rep(mask,1<<n){
        rep(i,n)rep(j,i)rep(k,4){
            int nmask = (mask|m[i][j][k]);
            dp[nmask] = min(dp[nmask], dp[mask]+1);
        }
    }

    int ans = dp[(1<<n)-1];
    assert(ans<n);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3428
final_rank: 1