Problem:
ねこまっしぐら
あるところに、高い塀に囲まれた大きなお屋敷がありました。そのお屋敷の主人は猫がとても大好きで、時折やってくる猫たちのために、いつもおいしいごはんを用意していました。お腹を空かせた猫たちは、高い塀をひょいと飛び越え、お屋敷の至る所に置いてあるごはんにまっしぐらに駆け寄るのでした。
ある日主人は、屋敷の中で何匹かの猫が倒れているのを見つけました。猫たちはごはんを探して屋敷の中を縦横無尽に走り回ったので、ぶつかったり転んだりしてしまったのです。主人は猫たちの安全を考えて、ごはんの置き場所を工夫することにしました。
上空から見ると、このお屋敷の塀は多角形をなしています。主人は猫たちがごはんを見つけやすいように、敷地内の中でも、多角形の頂点にあたる場所だけにごはんを置くことにしました。また猫たちは気まぐれなので、多角形の周上のどの点からお屋敷に入ってくるかは予想できません。そこで主人は、猫がどの点から入ったとしても、その点から直進していずれかのごはんにたどり着けるように、ごはんを配置することも決めました。
すべての頂点にごはんを配置すれば、この条件を満たすことができます。しかし、ごはんを補充して回るのは大変なので、主人はできるだけ少ない数の頂点にごはんを配置したいと思いました。さて、主人は最低何箇所にごはんを配置する必要があるでしょうか。
お屋敷の塀を表す多角形を入力とし、ごはんを配置する頂点の数の最小値を求めるプログラムを作成して下さい。ただし、猫は多角形の内部のみを直進できるものとします（辺は多角形の内部に含めるものとします）。
入力
入力は複数のデータセットからなる。入力の終わりはゼロ１つの行で示される。各データセットは以下の形式で与えられる。
n
x
1
y
1
x
2
y
2
...
x
n
y
n
１行目に多角形の頂点の数 n (3 ≤ n ≤ 16) が与えられる。続く n 行に多角形の頂点の座標が与えられる。n 行のそれぞれは、１つの空白で区切られた２つの整数からなる。x
i
(-1000 ≤ x
i
≤ 1000) は i 番目の頂点の x 座標、y
i
(-1000 ≤ y
i
≤ 1000) は i 番目の頂点の y 座標を示す。多角形の頂点は、隣り合った頂点を反時計回りに訪問するような順番で与えられる。
データセットの数は 20 を超えない。
出力
各データセットごとに、ご飯を配置する頂点の数を１行に出力する。
入力例
8
0 0
3 2
6 2
8 6
6 5
7 7
0 4
3 4
8
0 0
5 3
5 2
4 1
6 1
8 6
6 4
2 4
0
出力例
1
2

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;




#define MAX 16
#define SIZE 1000

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}
	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};


int N;
int POW[MAX+1];
double NUM = 10000;
bool check[MAX+1][SIZE];
Line line[MAX+1];
vector<Point> POINTS[MAX+1];
vector<Line> LINE;


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

void func(){

	for(int i = 0; i <= MAX; i++){

		POINTS[i].clear();
	}

	Polygon poly;

	double x,y;
	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&x,&y);
		poly.push_back(Point(x,y));
	}

	for(int i = 0; i < N; i++){

		line[i] = Line(poly[i],poly[(i+1)%N]);

		POINTS[i].push_back(poly[i]);
		POINTS[i].push_back(poly[(i+1)%N]);
	}

	//2点を通る直線を調べる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(k == i)continue;

			Vector vec = poly[k]-poly[i];

			Line tmp_line = Line(poly[i],poly[i]+vec*NUM); //点k方向に伸ばす

			for(int a = 0; a < N; a++){
				if(is_Cross(tmp_line,line[a])){

					Point cross_p = calc_Cross_Point(tmp_line,line[a]);
					POINTS[a].push_back(cross_p);
				}
			}
		}
	}

	for(int i = 0; i < N; i++){

		sort(POINTS[i].begin(),POINTS[i].end());
		POINTS[i].erase(unique(POINTS[i].begin(),POINTS[i].end()),POINTS[i].end());
	}

	LINE.clear();

	for(int i = 0; i < N; i++){
		for(int k = 1; k < POINTS[i].size(); k++){

			LINE.push_back(Line(POINTS[i][k-1],POINTS[i][k]));
		}
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < LINE.size(); k++){

			check[i][k] = false;
		}
	}

	for(int i = 0; i < N; i++){

		Point base_p = poly[i];

		for(int k = 0; k < LINE.size(); k++){

			//線分kからiが見えるか
			if(getDistanceSP(LINE[k],base_p) < EPS){

				check[i][k] = true;
				continue;
			}

			Polygon work_p;
			work_p.push_back(LINE[k].p[0]);
			work_p.push_back(LINE[k].p[1]);
			work_p.push_back(base_p);

			Point p_w = (work_p[0]+work_p[1]+work_p[2])/3;

			if(contains(poly,p_w) == 0){
				continue; //三角形の重心がポリゴンの外部ならSKIP
			}

			bool FLG = true;

			for(int a = 0; a < 3; a++){ //3つの辺について試す

				Line tmp_line = Line(work_p[a],work_p[(a+1)%3]);
				Vector base_vec = work_p[a]-work_p[(a+1)%3];

				for(int b = 0; b < N; b++){

					Vector adj = line[b].p[1]-line[b].p[0];

					if(line[b].p[0] == tmp_line.p[0] || line[b].p[0] == tmp_line.p[1] ||
												line[b].p[1] == tmp_line.p[0] || line[b].p[1] == tmp_line.p[1])continue;

					if(fabs(cross(base_vec,adj)) < EPS)continue;


					if(is_Cross(tmp_line,line[b])){

						Point cross_p = calc_Cross_Point(tmp_line,line[b]);
						if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1] || cross_p == line[b].p[0] || cross_p == line[b].p[1])continue;

						FLG = false;
						break;
					}
				}
				if(!FLG)break;
			}

			check[i][k] = FLG;
		}
	}


	int ans = N;
	bool table[LINE.size()];

	for(int state = 1; state < POW[N]; state++){

		for(int i = 0; i < LINE.size(); i++){

			table[i] = false;
		}

		int num_P = 0;

		for(int loop = 0; loop < N; loop++){
			if(state&POW[loop]){

				num_P++;

				for(int a = 0; a < LINE.size(); a++){

					table[a] |= check[loop][a];
				}
			}
		}

		bool FLG= true;
		for(int i = 0; i < LINE.size(); i++){
			if(!table[i]){

				FLG = false;
				break;
			}
		}

		if(FLG){

			ans = min(ans,num_P);
		}
	}

	printf("%d\n",ans);
}


int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){

		scanf("%d",&N);
		if(N == 0)break;

		func();
	}


	return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 3308
final_rank: 6

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;




#define MAX 16
#define SIZE 1000

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}
	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};


int N;
int POW[MAX+1];
double NUM = 10000;
bool check[MAX+1][SIZE];
Line line[MAX+1];
vector<Point> POINTS[MAX+1];
vector<Line> LINE;


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

bool DEBUG = false;

void func(){

	for(int i = 0; i <= MAX; i++){

		POINTS[i].clear();
	}

	Polygon poly;

	double x,y;
	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&x,&y);
		poly.push_back(Point(x,y));
	}

	for(int i = 0; i < N; i++){

		line[i] = Line(poly[i],poly[(i+1)%N]);

		POINTS[i].push_back(poly[i]);
		POINTS[i].push_back(poly[(i+1)%N]);
	}

	//2点を通る直線を調べる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(k == i)continue;

			Vector vec = poly[k]-poly[i];

			Line tmp_line = Line(poly[i],poly[i]+vec*NUM); //点k方向に伸ばす

			for(int a = 0; a < N; a++){
				if(is_Cross(tmp_line,line[a])){

					Point cross_p = calc_Cross_Point(tmp_line,line[a]);
					POINTS[a].push_back(cross_p);
				}
			}
		}
	}

	for(int i = 0; i < N; i++){

		sort(POINTS[i].begin(),POINTS[i].end());
		POINTS[i].erase(unique(POINTS[i].begin(),POINTS[i].end()),POINTS[i].end());
	}

	LINE.clear();

	for(int i = 0; i < N; i++){
		for(int k = 1; k < POINTS[i].size(); k++){

			LINE.push_back(Line(POINTS[i][k-1],POINTS[i][k]));
		}
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < LINE.size(); k++){

			check[i][k] = false;
		}
	}

	//if(DEBUG){
	//printf("LINE.size():%lld\n",LINE.size());
	//}

	for(int i = 0; i < N; i++){

		Point base_p = poly[i];

		if(DEBUG){
			printf("\n点%d",i);
			base_p.debug();
		}

		for(int k = 0; k < LINE.size(); k++){

			/*if(DEBUG){
				printf("線分\n");
				LINE[k].outPut();
			}*/

			//線分kからiが見えるか
			if(getDistanceSP(LINE[k],base_p) < EPS){

				check[i][k] = true;
				continue;
			}

			Polygon work_p;
			work_p.push_back(LINE[k].p[0]);
			work_p.push_back(LINE[k].p[1]);
			work_p.push_back(base_p);

			Point p_w = (work_p[0]+work_p[1]+work_p[2])/3;

			if(contains(poly,p_w) == 0){
				//printf("外部\n");
				continue; //三角形の重心がポリゴンの外部ならSKIP
			}

			bool FLG = true;

			for(int a = 0; a < 3; a++){ //3つの辺について試す

				Line tmp_line = Line(work_p[a],work_p[(a+1)%3]);
				Vector base_vec = work_p[a]-work_p[(a+1)%3];

				Point mid_p = (work_p[a]+work_p[(a+1)%3])/2;
				/*if(contains(poly,mid_p) == 0){

					FLG = false;
					break;
				}*/

				for(int b = 0; b < N; b++){

					Vector adj = line[b].p[1]-line[b].p[0];

					if(line[b].p[0] == tmp_line.p[0] || line[b].p[0] == tmp_line.p[1] ||
												line[b].p[1] == tmp_line.p[0] || line[b].p[1] == tmp_line.p[1])continue;

					if(fabs(cross(base_vec,adj)) < EPS)continue;


					if(is_Cross(tmp_line,line[b])){

						Point cross_p = calc_Cross_Point(tmp_line,line[b]);
						if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1] || cross_p == line[b].p[0] || cross_p == line[b].p[1])continue;
						//if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1])continue;

						/*if(DEBUG){
							printf("交差\n");
							line[b].outPut();
							cross_p.debug();
						}*/


						FLG = false;
						break;
					}
				}
				if(!FLG)break;
			}

			if(DEBUG){
				if(FLG){
					printf("線分");
					LINE[k].outPut();
					printf("から");
					base_p.debug();
					printf("見える\n");
				}else{

					printf("見えない\n");
				}
			}

			check[i][k] = FLG;
		}
	}


	int ans = N;
	bool table[LINE.size()];

	for(int state = 1; state < POW[N]; state++){

		for(int i = 0; i < LINE.size(); i++){

			table[i] = false;
		}

		int num_P = 0;

		for(int loop = 0; loop < N; loop++){
			if(state&POW[loop]){

				num_P++;

				for(int a = 0; a < LINE.size(); a++){

					table[a] |= check[loop][a];
				}
			}
		}

		bool FLG= true;
		for(int i = 0; i < LINE.size(); i++){
			if(!table[i]){

				FLG = false;
				break;
			}
		}

		if(FLG){

			ans = min(ans,num_P);
		}
	}

	printf("%d\n",ans);
}


int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){

		scanf("%d",&N);
		if(N == 0)break;

		func();
	}


	return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 3272
final_rank: 4

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;




#define MAX 16
#define SIZE 1000

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}
	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};


int N;
int POW[MAX+1];
double NUM = 10000;
bool check[MAX+1][SIZE];
Line line[MAX+1];
vector<Point> POINTS[MAX+1];
vector<Line> LINE;


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

bool DEBUG = false;

void func(){

	for(int i = 0; i <= MAX; i++){

		POINTS[i].clear();
	}

	Polygon poly;

	double x,y;
	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&x,&y);
		poly.push_back(Point(x,y));
	}

	for(int i = 0; i < N; i++){

		line[i] = Line(poly[i],poly[(i+1)%N]);

		POINTS[i].push_back(poly[i]);
		POINTS[i].push_back(poly[(i+1)%N]);
	}

	//2点を通る直線を調べる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(k == i)continue;

			Vector vec = poly[k]-poly[i];

			Line tmp_line = Line(poly[i],poly[i]+vec*NUM); //点k方向に伸ばす

			for(int a = 0; a < N; a++){
				if(is_Cross(tmp_line,line[a])){

					Point cross_p = calc_Cross_Point(tmp_line,line[a]);
					POINTS[a].push_back(cross_p);
				}
			}
		}
	}

	for(int i = 0; i < N; i++){

		sort(POINTS[i].begin(),POINTS[i].end());
		POINTS[i].erase(unique(POINTS[i].begin(),POINTS[i].end()),POINTS[i].end());
	}

	LINE.clear();

	for(int i = 0; i < N; i++){
		for(int k = 1; k < POINTS[i].size(); k++){

			LINE.push_back(Line(POINTS[i][k-1],POINTS[i][k]));
		}
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < LINE.size(); k++){

			check[i][k] = false;
		}
	}

	if(DEBUG){
	printf("LINE.size():%lld\n",LINE.size());
	}

	for(int i = 0; i < N; i++){

		Point base_p = poly[i];

		if(DEBUG){
			printf("\n点%d",i);
			base_p.debug();
		}

		for(int k = 0; k < LINE.size(); k++){

			/*if(DEBUG){
				printf("線分\n");
				LINE[k].outPut();
			}*/

			//線分kからiが見えるか
			if(getDistanceSP(LINE[k],base_p) < EPS){

				check[i][k] = true;
				continue;
			}

			Polygon work_p;
			work_p.push_back(LINE[k].p[0]);
			work_p.push_back(LINE[k].p[1]);
			work_p.push_back(base_p);

			Point p_w = (work_p[0]+work_p[1]+work_p[2])/3;

			if(contains(poly,p_w) == 0){
				//printf("外部\n");
				continue; //三角形の重心がポリゴンの外部ならSKIP
			}

			bool FLG = true;

			for(int a = 0; a < 3; a++){ //3つの辺について試す

				Line tmp_line = Line(work_p[a],work_p[(a+1)%3]);
				Vector base_vec = work_p[a]-work_p[(a+1)%3];

				Point mid_p = (work_p[a]+work_p[(a+1)%3])/2;
				if(contains(poly,mid_p) == 0){

					FLG = false;
					break;
				}

				for(int b = 0; b < N; b++){

					Vector adj = line[b].p[1]-line[b].p[0];

					if(line[b].p[0] == tmp_line.p[0] || line[b].p[0] == tmp_line.p[1] ||
												line[b].p[1] == tmp_line.p[0] || line[b].p[1] == tmp_line.p[1])continue;

					if(fabs(cross(base_vec,adj)) < EPS)continue;


					if(is_Cross(tmp_line,line[b])){

						Point cross_p = calc_Cross_Point(tmp_line,line[b]);
						if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1] || cross_p == line[b].p[0] || cross_p == line[b].p[1])continue;
						//if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1])continue;

						/*if(DEBUG){
							printf("交差\n");
							line[b].outPut();
							cross_p.debug();
						}*/


						FLG = false;
						break;
					}
				}
				if(!FLG)break;
			}

			if(DEBUG){
				if(FLG){
					printf("線分");
					LINE[k].outPut();
					printf("から");
					base_p.debug();
					printf("見える\n");
				}else{

					printf("見えない\n");
				}
			}

			check[i][k] = FLG;
		}
	}


	int ans = N;
	bool table[LINE.size()];

	for(int state = 1; state < POW[N]; state++){

		for(int i = 0; i < LINE.size(); i++){

			table[i] = false;
		}

		int num_P = 0;

		for(int loop = 0; loop < N; loop++){
			if(state&POW[loop]){

				num_P++;

				for(int a = 0; a < LINE.size(); a++){

					table[a] |= check[loop][a];
				}
			}
		}

		bool FLG= true;
		for(int i = 0; i < LINE.size(); i++){
			if(!table[i]){

				FLG = false;
				break;
			}
		}

		if(FLG){

			ans = min(ans,num_P);
		}
	}

	printf("%d\n",ans);
}


int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){

		scanf("%d",&N);
		if(N == 0)break;

		func();
	}


	return 0;
}
accuracy: 0.8571428571428571
time_ms: 340
memory_kb: 3308
final_rank: 8

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;




#define MAX 16

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}
	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};


int N;
int POW[MAX+1];
double NUM = 10000;
bool check[MAX+1][300];
Line line[MAX+1];
vector<Point> POINTS[MAX+1];
vector<Line> LINE;


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

bool DEBUG = false;

void func(){

	for(int i = 0; i <= MAX; i++){

		POINTS[i].clear();
	}

	Polygon poly;

	double x,y;
	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&x,&y);
		poly.push_back(Point(x,y));
	}

	for(int i = 0; i < N; i++){

		line[i] = Line(poly[i],poly[(i+1)%N]);

		POINTS[i].push_back(poly[i]);
		POINTS[i].push_back(poly[(i+1)%N]);
	}

	//2点を通る直線を調べる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(k == i)continue;

			Vector vec = poly[k]-poly[i];

			Line tmp_line = Line(poly[i],poly[i]+vec*NUM); //点k方向に伸ばす

			for(int a = 0; a < N; a++){
				if(is_Cross(tmp_line,line[a])){

					Point cross_p = calc_Cross_Point(tmp_line,line[a]);
					POINTS[a].push_back(cross_p);
				}
			}
		}
	}

	for(int i = 0; i < N; i++){

		sort(POINTS[i].begin(),POINTS[i].end());
		POINTS[i].erase(unique(POINTS[i].begin(),POINTS[i].end()),POINTS[i].end());
	}

	LINE.clear();

	for(int i = 0; i < N; i++){
		for(int k = 1; k < POINTS[i].size(); k++){

			LINE.push_back(Line(POINTS[i][k-1],POINTS[i][k]));
		}
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < LINE.size(); k++){

			check[i][k] = false;
		}
	}

	for(int i = 0; i < N; i++){

		Point base_p = poly[i];

		if(DEBUG){
			printf("\n点%d",i);
			base_p.debug();
		}

		for(int k = 0; k < LINE.size(); k++){

			if(DEBUG){
				printf("線分\n");
				LINE[k].outPut();
			}

			//線分kからiが見えるか
			if(getDistanceSP(LINE[k],base_p) < EPS){

				check[i][k] = true;
				continue;
			}

			Polygon work_p;
			work_p.push_back(LINE[k].p[0]);
			work_p.push_back(LINE[k].p[1]);
			work_p.push_back(base_p);

			Point p_w = (work_p[0]+work_p[1]+work_p[2])/3;

			if(contains(poly,p_w) == 0){
				//printf("外部\n");
				continue; //三角形の重心がポリゴンの外部ならSKIP
			}

			bool FLG = true;

			for(int a = 0; a < 3; a++){ //3つの辺について試す

				Line tmp_line = Line(work_p[a],work_p[(a+1)%3]);
				Vector base_vec = work_p[a]-work_p[(a+1)%3];

				for(int b = 0; b < N; b++){

					Vector adj = line[b].p[1]-line[b].p[0];

					if(line[b].p[0] == tmp_line.p[0] || line[b].p[0] == tmp_line.p[1] ||
												line[b].p[1] == tmp_line.p[0] || line[b].p[1] == tmp_line.p[1])continue;

					if(fabs(cross(base_vec,adj)) < EPS)continue;


					if(is_Cross(tmp_line,line[b])){

						Point cross_p = calc_Cross_Point(tmp_line,line[b]);
						if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1] || cross_p == line[b].p[0] || cross_p == line[b].p[1])continue;
						//if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1])continue;

						if(DEBUG){
							printf("交差\n");
							line[b].outPut();
							cross_p.debug();
						}


						FLG = false;
						break;
					}
				}
				if(!FLG)break;
			}

			if(DEBUG){
				if(FLG){

					printf("見える\n");
				}else{

					printf("見えない\n");
				}
			}

			check[i][k] = FLG;
		}
	}


	int ans = N;
	bool table[LINE.size()];

	for(int state = 1; state < POW[N]; state++){

		for(int i = 0; i < LINE.size(); i++){

			table[i] = false;
		}

		int num_P = 0;

		for(int loop = 0; loop < N; loop++){
			if(state&POW[loop]){

				num_P++;

				for(int a = 0; a < LINE.size(); a++){

					table[a] |= check[loop][a];
				}
			}
		}

		bool FLG= true;
		for(int i = 0; i < LINE.size(); i++){
			if(!table[i]){

				FLG = false;
				break;
			}
		}

		if(FLG){

			ans = min(ans,num_P);
		}
	}

	printf("%d\n",ans);
}


int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){

		scanf("%d",&N);
		if(N == 0)break;

		func();
	}


	return 0;
}
accuracy: 0.7142857142857143
time_ms: 360
memory_kb: 3264
final_rank: 9

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;




#define MAX 16

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}
	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};


int N;
int POW[MAX+1];
double NUM = 10000;
bool check[MAX+1][300];
Line line[MAX+1];
vector<Point> POINTS[MAX+1];
vector<Line> LINE;


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

bool DEBUG = false;

void func(){

	for(int i = 0; i <= MAX; i++){

		POINTS[i].clear();
	}

	Polygon poly;

	double x,y;
	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&x,&y);
		poly.push_back(Point(x,y));
	}

	for(int i = 0; i < N; i++){

		line[i] = Line(poly[i],poly[(i+1)%N]);

		POINTS[i].push_back(poly[i]);
		POINTS[i].push_back(poly[(i+1)%N]);
	}

	//2点を通る直線を調べる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(k == i)continue;

			Vector vec = poly[k]-poly[i];

			Line tmp_line = Line(poly[i],poly[i]+vec*NUM); //点k方向に伸ばす

			for(int a = 0; a < N; a++){
				if(is_Cross(tmp_line,line[a])){

					Point cross_p = calc_Cross_Point(tmp_line,line[a]);
					POINTS[a].push_back(cross_p);
				}
			}
		}
	}

	for(int i = 0; i < N; i++){

		sort(POINTS[i].begin(),POINTS[i].end());
		POINTS[i].erase(unique(POINTS[i].begin(),POINTS[i].end()),POINTS[i].end());
	}

	LINE.clear();

	for(int i = 0; i < N; i++){
		for(int k = 1; k < POINTS[i].size(); k++){

			LINE.push_back(Line(POINTS[i][k-1],POINTS[i][k]));
		}
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < LINE.size(); k++){

			check[i][k] = false;
		}
	}

	for(int i = 0; i < N; i++){

		Point base_p = poly[i];

		if(DEBUG){
			printf("\n点%d",i);
			base_p.debug();
		}

		for(int k = 0; k < LINE.size(); k++){

			if(DEBUG){
				printf("線分\n");
				LINE[k].outPut();
			}

			//線分kからiが見えるか
			if(getDistanceSP(LINE[k],base_p) < EPS){

				check[i][k] = true;
				continue;
			}

			Polygon work_p;
			work_p.push_back(LINE[k].p[0]);
			work_p.push_back(LINE[k].p[1]);
			work_p.push_back(base_p);

			Point p_w = (work_p[0]+work_p[1]+work_p[2])/3;

			if(contains(poly,p_w) == 0){
				//printf("外部\n");
				continue; //三角形の重心がポリゴンの外部ならSKIP
			}

			bool FLG = true;

			for(int a = 0; a < 3; a++){ //3つの辺について試す

				Line tmp_line = Line(work_p[a],work_p[(a+1)%3]);
				Vector base_vec = work_p[a]-work_p[(a+1)%3];

				for(int b = 0; b < N; b++){

					Vector adj = line[b].p[1]-line[b].p[0];

					if(fabs(cross(base_vec,adj)) < EPS)continue;


					if(line[b].p[0] == tmp_line.p[0] || line[b].p[0] == tmp_line.p[1] ||
							line[b].p[1] == tmp_line.p[0] || line[b].p[1] == tmp_line.p[1])continue;

					if(is_Cross(tmp_line,line[b])){

						Point cross_p = calc_Cross_Point(tmp_line,line[b]);
						//if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1] || cross_p == line[b].p[0] || cross_p == line[b].p[1])continue;
						if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1])continue;

						if(DEBUG){
							printf("交差\n");
							line[b].outPut();
							cross_p.debug();
						}


						FLG = false;
						break;
					}
				}
				if(!FLG)break;
			}

			if(DEBUG){
				if(FLG){

					printf("見える\n");
				}else{

					printf("見えない\n");
				}
			}

			check[i][k] = FLG;
		}
	}


	int ans = N;
	bool table[LINE.size()];

	for(int state = 1; state < POW[N]; state++){

		for(int i = 0; i < LINE.size(); i++){

			table[i] = false;
		}

		int num_P = 0;

		for(int loop = 0; loop < N; loop++){
			if(state&POW[loop]){

				num_P++;

				for(int a = 0; a < LINE.size(); a++){

					table[a] |= check[loop][a];
				}
			}
		}

		bool FLG= true;
		for(int i = 0; i < LINE.size(); i++){
			if(!table[i]){

				FLG = false;
				break;
			}
		}

		if(FLG){

			ans = min(ans,num_P);
		}
	}

	printf("%d\n",ans);
}


int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){

		scanf("%d",&N);
		if(N == 0)break;

		func();
	}


	return 0;
}
accuracy: 0.42857142857142855
time_ms: 110
memory_kb: 3264
final_rank: 15

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;




#define MAX 16

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}
	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};


int N;
int POW[MAX+1];
double NUM = 10000;
bool check[MAX+1][300];
Line line[MAX+1];
vector<Point> POINTS[MAX+1];
vector<Line> LINE;


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

bool DEBUG = false;

void func(){

	for(int i = 0; i <= MAX; i++){

		POINTS[i].clear();
	}

	Polygon poly;

	double x,y;
	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&x,&y);
		poly.push_back(Point(x,y));
	}

	for(int i = 0; i < N; i++){

		line[i] = Line(poly[i],poly[(i+1)%N]);

		POINTS[i].push_back(poly[i]);
		POINTS[i].push_back(poly[(i+1)%N]);
	}

	//2点を通る直線を調べる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(k == i)continue;

			Vector vec = poly[k]-poly[i];

			Line tmp_line = Line(poly[i],poly[i]+vec*NUM); //点k方向に伸ばす

			for(int a = 0; a < N; a++){
				if(is_Cross(tmp_line,line[a])){

					Point cross_p = calc_Cross_Point(tmp_line,line[a]);
					POINTS[a].push_back(cross_p);
				}
			}
		}
	}

	for(int i = 0; i < N; i++){

		sort(POINTS[i].begin(),POINTS[i].end());
		POINTS[i].erase(unique(POINTS[i].begin(),POINTS[i].end()),POINTS[i].end());
	}

	LINE.clear();

	for(int i = 0; i < N; i++){
		for(int k = 1; k < POINTS[i].size(); k++){

			LINE.push_back(Line(POINTS[i][k-1],POINTS[i][k]));
		}
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < LINE.size(); k++){

			check[i][k] = false;
		}
	}

	for(int i = 0; i < N; i++){

		Point base_p = poly[i];

		if(DEBUG){
			printf("\n点%d",i);
			base_p.debug();
		}

		for(int k = 0; k < LINE.size(); k++){

			if(DEBUG){
				printf("線分\n");
				LINE[k].outPut();
			}

			//線分kからiが見えるか
			if(getDistanceSP(LINE[k],base_p) < EPS){

				check[i][k] = true;
				continue;
			}

			Polygon work_p;
			work_p.push_back(LINE[k].p[0]);
			work_p.push_back(LINE[k].p[1]);
			work_p.push_back(base_p);

			Point p_w = (work_p[0]+work_p[1]+work_p[2])/3;

			if(contains(poly,p_w) == 0){
				//printf("外部\n");
				continue; //三角形の重心がポリゴンの外部ならSKIP
			}

			bool FLG = true;

			for(int a = 0; a < 3; a++){ //3つの辺について試す
				Line tmp_line = Line(work_p[a],work_p[(a+1)%3]);
				double base_slope = calc_slope(tmp_line);

				for(int b = 0; b < N; b++){

					double tmp_slope = calc_slope(line[b]);
					if(fabs(base_slope-tmp_slope) < EPS)continue;
					if(line[b].p[0] == tmp_line.p[0] || line[b].p[0] == tmp_line.p[1] ||
							line[b].p[1] == tmp_line.p[0] || line[b].p[1] == tmp_line.p[1])continue;

					if(is_Cross(tmp_line,line[b])){

						Point cross_p = calc_Cross_Point(tmp_line,line[b]);
						if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1] || cross_p == line[b].p[0] || cross_p == line[b].p[1])continue;

						if(DEBUG){
							printf("交差\n");
							line[b].outPut();
							cross_p.debug();
						}


						FLG = false;
						break;
					}
				}
				if(!FLG)break;
			}

			if(DEBUG){
				if(FLG){

					printf("見える\n");
				}else{

					printf("見えない\n");
				}
			}

			check[i][k] = FLG;
		}
	}


	int ans = N;
	bool table[LINE.size()];

	for(int state = 1; state < POW[N]; state++){

		for(int i = 0; i < LINE.size(); i++){

			table[i] = false;
		}

		int num_P = 0;

		for(int loop = 0; loop < N; loop++){
			if(state&POW[loop]){

				num_P++;

				for(int a = 0; a < LINE.size(); a++){

					table[a] |= check[loop][a];
				}
			}
		}

		bool FLG= true;
		for(int i = 0; i < LINE.size(); i++){
			if(!table[i]){

				FLG = false;
				break;
			}
		}

		if(FLG){

			ans = min(ans,num_P);
		}
	}

	printf("%d\n",ans);
}


int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){

		scanf("%d",&N);
		if(N == 0)break;

		func();
	}


	return 0;
}
accuracy: 0.7142857142857143
time_ms: 360
memory_kb: 3336
final_rank: 11

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;



#define EPS 0.0000001
#define MAX 16

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}
	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};


int N;
int POW[MAX+1];
double NUM = 10000;
bool check[MAX+1][300];
Line line[MAX+1];
vector<Point> POINTS[MAX+1];
vector<Line> LINE;


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

bool DEBUG = false;

void func(){

	for(int i = 0; i <= MAX; i++){

		POINTS[i].clear();
	}

	Polygon poly;

	double x,y;
	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&x,&y);
		poly.push_back(Point(x,y));
	}

	for(int i = 0; i < N; i++){

		line[i] = Line(poly[i],poly[(i+1)%N]);

		POINTS[i].push_back(poly[i]);
		POINTS[i].push_back(poly[(i+1)%N]);
	}

	//2点を通る直線を調べる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(k == i)continue;

			Vector vec = poly[k]-poly[i];

			Line tmp_line = Line(poly[i],poly[i]+vec*NUM); //点k方向に伸ばす

			for(int a = 0; a < N; a++){
				if(is_Cross(tmp_line,line[a])){

					Point cross_p = calc_Cross_Point(tmp_line,line[a]);
					POINTS[a].push_back(cross_p);
				}
			}
		}
	}

	for(int i = 0; i < N; i++){

		sort(POINTS[i].begin(),POINTS[i].end());
		POINTS[i].erase(unique(POINTS[i].begin(),POINTS[i].end()),POINTS[i].end());
	}

	LINE.clear();

	for(int i = 0; i < N; i++){
		for(int k = 1; k < POINTS[i].size(); k++){

			LINE.push_back(Line(POINTS[i][k-1],POINTS[i][k]));
		}
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < LINE.size(); k++){

			check[i][k] = false;
		}
	}

	for(int i = 0; i < N; i++){

		Point base_p = poly[i];

		if(DEBUG){
			printf("\n点%d",i);
			base_p.debug();
		}

		for(int k = 0; k < LINE.size(); k++){

			if(DEBUG){
				printf("線分\n");
				LINE[k].outPut();
			}

			//線分kからiが見えるか
			Polygon work_p;
			work_p.push_back(LINE[k].p[0]);
			work_p.push_back(LINE[k].p[1]);
			work_p.push_back(base_p);

			Point p_w = (work_p[0]+work_p[1]+work_p[2])/3;

			if(contains(poly,p_w) == 0){
				//printf("外部\n");
				continue; //三角形の重心がポリゴンの外部ならSKIP
			}

			Point mid_p = (LINE[k].p[0]+LINE[k].p[1])/2;
			Line tmp_line = Line(mid_p,base_p);

			bool FLG = true;

			for(int b = 0; b < N; b++){

				if(getDistanceSP(line[b],mid_p) < EPS || getDistanceSP(line[b],base_p) < EPS)continue;

				if(is_Cross(tmp_line,line[b])){

					Point cross_p = calc_Cross_Point(tmp_line,line[b]);
					//if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1] || cross_p == line[b].p[0] || cross_p == line[b].p[1])continue;

					if(DEBUG){
						printf("交差\n");
						line[b].outPut();
						cross_p.debug();
					}


					FLG = false;
					break;
				}
			}

			if(DEBUG){
				if(FLG){

					printf("見える\n");
				}else{

					printf("見えない\n");
				}
			}

			check[i][k] = FLG;
		}
	}


	int ans = N;
	bool table[LINE.size()];

	for(int state = 1; state < POW[N]; state++){

		for(int i = 0; i < LINE.size(); i++){

			table[i] = false;
		}

		int num_P = 0;

		for(int loop = 0; loop < N; loop++){
			if(state&POW[loop]){

				num_P++;

				for(int a = 0; a < LINE.size(); a++){

					table[a] |= check[loop][a];
				}
			}
		}

		bool FLG= true;
		for(int i = 0; i < LINE.size(); i++){
			if(!table[i]){

				FLG = false;
				break;
			}
		}

		if(FLG){

			ans = min(ans,num_P);
		}
	}

	printf("%d\n",ans);
}


int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){

		scanf("%d",&N);
		if(N == 0)break;

		func();
	}


	return 0;
}
accuracy: 0.42857142857142855
time_ms: 100
memory_kb: 3300
final_rank: 19

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;




#define MAX 16

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}
	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};


int N;
int POW[MAX+1];
double NUM = 10000;
bool check[MAX+1][300];
Line line[MAX+1];
vector<Point> POINTS[MAX+1];
vector<Line> LINE;


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

bool DEBUG = false;

void func(){

	for(int i = 0; i <= MAX; i++){

		POINTS[i].clear();
	}

	Polygon poly;

	double x,y;
	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&x,&y);
		poly.push_back(Point(x,y));
	}

	for(int i = 0; i < N; i++){

		line[i] = Line(poly[i],poly[(i+1)%N]);

		POINTS[i].push_back(poly[i]);
		POINTS[i].push_back(poly[(i+1)%N]);
	}

	//2点を通る直線を調べる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(k == i)continue;

			Vector vec = poly[k]-poly[i];

			Line tmp_line = Line(poly[i],poly[i]+vec*NUM); //点k方向に伸ばす

			for(int a = 0; a < N; a++){
				if(is_Cross(tmp_line,line[a])){

					Point cross_p = calc_Cross_Point(tmp_line,line[a]);
					POINTS[a].push_back(cross_p);
				}
			}
		}
	}

	for(int i = 0; i < N; i++){

		sort(POINTS[i].begin(),POINTS[i].end());
		POINTS[i].erase(unique(POINTS[i].begin(),POINTS[i].end()),POINTS[i].end());
	}

	LINE.clear();

	for(int i = 0; i < N; i++){
		for(int k = 1; k < POINTS[i].size(); k++){

			LINE.push_back(Line(POINTS[i][k-1],POINTS[i][k]));
		}
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < LINE.size(); k++){

			check[i][k] = false;
		}
	}

	for(int i = 0; i < N; i++){

		Point base_p = poly[i];

		if(DEBUG){
			printf("\n点%d",i);
			base_p.debug();
		}

		for(int k = 0; k < LINE.size(); k++){

			if(DEBUG){
				printf("線分\n");
				LINE[k].outPut();
			}

			//線分kからiが見えるか
			Polygon work_p;
			work_p.push_back(LINE[k].p[0]);
			work_p.push_back(LINE[k].p[1]);
			work_p.push_back(base_p);

			Point p_w = (work_p[0]+work_p[1]+work_p[2])/3;

			if(contains(poly,p_w) == 0){
				//printf("外部\n");
				continue; //三角形の重心がポリゴンの外部ならSKIP
			}

			bool FLG = true;

			for(int a = 0; a < 3; a++){ //3つの辺について試す
				Line tmp_line = Line(work_p[a],work_p[(a+1)%3]);
				double base_slope = calc_slope(tmp_line);

				for(int b = 0; b < N; b++){

					double tmp_slope = calc_slope(line[b]);
					if(fabs(base_slope-tmp_slope) < EPS)continue;
					if(line[b].p[0] == tmp_line.p[0] || line[b].p[0] == tmp_line.p[1] ||
							line[b].p[1] == tmp_line.p[0] || line[b].p[1] == tmp_line.p[1])continue;

					if(is_Cross(tmp_line,line[b])){

						Point cross_p = calc_Cross_Point(tmp_line,line[b]);
						if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1] || cross_p == line[b].p[0] || cross_p == line[b].p[1])continue;

						if(DEBUG){
							printf("交差\n");
							line[b].outPut();
							cross_p.debug();
						}


						FLG = false;
						break;
					}
				}
				if(!FLG)break;
			}

			if(DEBUG){
				if(FLG){

					printf("見える\n");
				}else{

					printf("見えない\n");
				}
			}

			check[i][k] = FLG;
		}
	}


	int ans = N;
	bool table[LINE.size()];

	for(int state = 1; state < POW[N]; state++){

		for(int i = 0; i < LINE.size(); i++){

			table[i] = false;
		}

		int num_P = 0;

		for(int loop = 0; loop < N; loop++){
			if(state&POW[loop]){

				num_P++;

				for(int a = 0; a < LINE.size(); a++){

					table[a] |= check[loop][a];
				}
			}
		}

		bool FLG= true;
		for(int i = 0; i < LINE.size(); i++){
			if(!table[i]){

				FLG = false;
				break;
			}
		}

		if(FLG){

			ans = min(ans,num_P);
		}
	}

	printf("%d\n",ans);
}


int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){

		scanf("%d",&N);
		if(N == 0)break;

		func();
	}


	return 0;
}
accuracy: 0.7142857142857143
time_ms: 360
memory_kb: 3300
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;




#define MAX 16

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}
	double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3lf,%.3lf)-(%.3lf,%.3lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};


int N;
int POW[MAX+1];
double NUM = 10000;
bool check[MAX+1][300];
Line line[MAX+1];
vector<Point> POINTS[MAX+1];
vector<Line> LINE;


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	if(getDistanceSP(B,A.p[0]) < EPS){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

bool DEBUG = false;

void func(){

	for(int i = 0; i <= MAX; i++){

		POINTS[i].clear();
	}

	Polygon poly;

	double x,y;
	for(int i = 0; i < N; i++){

		scanf("%lf %lf",&x,&y);
		poly.push_back(Point(x,y));
	}

	for(int i = 0; i < N; i++){

		line[i] = Line(poly[i],poly[(i+1)%N]);

		POINTS[i].push_back(poly[i]);
		POINTS[i].push_back(poly[(i+1)%N]);
	}

	//2点を通る直線を調べる
	for(int i = 0; i < N; i++){
		for(int k = 0; k < N; k++){
			if(k == i)continue;

			Vector vec = poly[k]-poly[i];

			Line tmp_line = Line(poly[i],poly[i]+vec*NUM); //点k方向に伸ばす

			for(int a = 0; a < N; a++){
				if(is_Cross(tmp_line,line[a])){

					Point cross_p = calc_Cross_Point(tmp_line,line[a]);
					POINTS[a].push_back(cross_p);
				}
			}
		}
	}

	for(int i = 0; i < N; i++){

		sort(POINTS[i].begin(),POINTS[i].end());
		POINTS[i].erase(unique(POINTS[i].begin(),POINTS[i].end()),POINTS[i].end());
	}

	LINE.clear();

	for(int i = 0; i < N; i++){
		for(int k = 1; k < POINTS[i].size(); k++){

			LINE.push_back(Line(POINTS[i][k-1],POINTS[i][k]));
		}
	}

	for(int i = 0; i < N; i++){
		for(int k = 0; k < LINE.size(); k++){

			check[i][k] = false;
		}
	}

	for(int i = 0; i < N; i++){

		Point base_p = poly[i];

		if(DEBUG){
			printf("\n点%d",i);
			base_p.debug();
		}

		for(int k = 0; k < LINE.size(); k++){

			if(DEBUG){
				printf("線分\n");
				LINE[k].outPut();
			}

			//線分kからiが見えるか
			Polygon work_p;
			work_p.push_back(LINE[k].p[0]);
			work_p.push_back(LINE[k].p[1]);
			work_p.push_back(base_p);

			Point p_w = (work_p[0]+work_p[1]+work_p[2])/3;

			if(contains(poly,p_w) == 0){
				//printf("外部\n");
				continue; //三角形の重心がポリゴンの外部ならSKIP
			}

			bool FLG = true;

			for(int a = 0; a < 3; a++){ //3つの辺について試す
				Line tmp_line = Line(work_p[a],work_p[(a+1)%3]);
				double base_slope = calc_slope(tmp_line);

				for(int b = 0; b < N; b++){

					double tmp_slope = calc_slope(line[b]);
					if(fabs(base_slope-tmp_slope) < EPS)continue;
					if(line[b].p[0] == tmp_line.p[0] || line[b].p[0] == tmp_line.p[1] ||
							line[b].p[1] == tmp_line.p[0] || line[b].p[1] == tmp_line.p[1])continue;

					if(is_Cross(tmp_line,line[b])){

						Point cross_p = calc_Cross_Point(tmp_line,line[b]);
						if(cross_p == tmp_line.p[0] || cross_p == tmp_line.p[1])continue;

						if(DEBUG){
							printf("交差\n");
							line[b].outPut();
							cross_p.debug();
						}


						FLG = false;
						break;
					}
				}
				if(!FLG)break;
			}

			if(DEBUG){
				if(FLG){

					printf("見える\n");
				}else{

					printf("見えない\n");
				}
			}

			check[i][k] = FLG;
		}
	}


	int ans = N;
	bool table[LINE.size()];

	for(int state = 1; state < POW[N]; state++){

		for(int i = 0; i < LINE.size(); i++){

			table[i] = false;
		}

		int num_P = 0;

		for(int loop = 0; loop < N; loop++){
			if(state&POW[loop]){

				num_P++;

				for(int a = 0; a < LINE.size(); a++){

					table[a] |= check[loop][a];
				}
			}
		}

		bool FLG= true;
		for(int i = 0; i < LINE.size(); i++){
			if(!table[i]){

				FLG = false;
				break;
			}
		}

		if(FLG){

			ans = min(ans,num_P);
		}
	}

	printf("%d\n",ans);
}


int main(){

	POW[0] = 1;
	for(int i = 1; i <= MAX; i++){

		POW[i] = POW[i-1]*2;
	}

	while(true){

		scanf("%d",&N);
		if(N == 0)break;

		func();
	}


	return 0;
}
accuracy: 0.42857142857142855
time_ms: 110
memory_kb: 3276
final_rank: 16

code_snippet: #include <iostream>
#include <complex>
#include <cstdio>
#include <utility>
#include <vector>
#include <bitset>
using namespace std;
typedef complex<double> P;
typedef pair<P,P> L;
typedef pair<P,double> C;
typedef vector<P> Poly;
#define X real()
#define Y imag()
const double EPS = (1e-10);
const double INF = (1e15);
  
namespace std{
  bool operator < (const P& a, const P& b){
    return a.X != b.X ? a.X < b.X : a.Y < b.Y;
  }
  bool operator == (const P& a, const P& b){
    return abs(a-b) < EPS;
  }
}

double dot(P a, P b){
  return a.X * b.X + a.Y * b.Y;
}
double cross(P a, P b){
  return a.X * b.Y - a.Y * b.X;
}

int ccw(P a, P b, P c){
  b -= a;
  c -= a;
  if(cross(b,c) > EPS) return 1;
  if(cross(b,c) < -EPS) return -1;
  if(dot(b,c) < -EPS) return 2;
  if(norm(c) - norm(b) > EPS) return -2;
  return 0;
}

bool is_cross(L a, L b){
  //接しているのはセーフ
  if(ccw(a.first,a.second,b.first)*ccw(a.first,a.second,b.second) < 0 &&
     ccw(b.first,b.second,a.first)*ccw(b.first,b.second,a.second) < 0)
    return true;
  return false;
}

int in_poly(P a, Poly p){
  int n = p.size(), c = 0;
  for(int i = 0; i < n; ++i){
    P s = p[i] - a, t = p[(i+1)%n] - a;
    if(!ccw(s,t,P(0,0))) return 1;//周上
    if(s.Y > t.Y + EPS) swap(s,t);
    if((s.Y*t.Y < 0 || (s.Y*t.Y < EPS && t.Y > EPS)) && cross(s,t) < EPS) ++c;
  }
  if(c%2) return 2;//内部
  return 0;//外
}

using namespace std;
int main(){
  int n;
  while(cin >> n, n){
    Poly V;
    for(int i = 0; i < n; ++i){
      double x, y;
      cin >> x >> y;
      V.push_back(P(x,y));
    }
    vector< vector<bool> > valid(n,vector<bool>(n,false));
    for(int i = 0; i < n; ++i){
      for(int j = 0; j < i; ++j){
        L l = L(V[i], V[j]);
        bool f = false;
        for(int k = 0; k < n; ++k){
          if(k == i || (k+1)%n == i || k == j || (k+1)%n == j) continue;
          f |= is_cross(l, L(V[k], V[(k+1)%n]));
          if(f){
            //cout << "(" << i << ", " << j << "), " << "(" << k << ", " << (k+1)%n << "), " << endl;
            break;
          }
        }
        if(f) continue;
        for(int k = 0; k < n; ++k){
          P m = V[i] + (V[j] - V[i])/(double)(n*k);
          if(!in_poly(m, V)) f = true;
        }
        if(f) continue;
        valid[i][j] = true;
        valid[j][i] = true;
      }
    }
    for(int i = 0; i < n; ++i){
      valid[i][i] = true;
      valid[i][(i+1)%n] = true;
      valid[(i+1)%n][i] = true;
    }
    /*
    for(int i = 0; i < n; ++i){
      for(int j = 0; j < n; ++j) cout << valid[i][j] << " ";cout << endl;
    }
    */
    int ans = n/3;
    for(int i = 1; i < (1<<n); ++i){
      vector<bool> ok(n, false);
      int c = 0;
      for(int j = 0; j < n; ++j){
        if(!((i>>j) & 1)) continue;
        ++c;
        for(int k = 0; k < n; ++k){
          //if(valid[j][k] && valid[j][(k+1)%n]) ok[k] = true;
          if(valid[j][k]) ok[k] = true;
        }
      }
      bool f = true;
      //cout << bitset<8>(i) << endl;
      //for(int j = 0; j < n; ++j) cout << ok[j] << " ";cout << endl;
      for(int j = 0; j < n; ++j) f &= ok[j];
      if(f) ans = min(ans, c);
      //if(f && c == 4) cout << bitset<16>(i) << endl;
    }
    cout << ans << endl;
  }
  return 0;
}
accuracy: 0.42857142857142855
time_ms: 20
memory_kb: 3284
final_rank: 17

code_snippet: #include <iostream>
#include <complex>
#include <cstdio>
#include <utility>
#include <vector>
#include <bitset>
using namespace std;
typedef complex<double> P;
typedef pair<P,P> L;
typedef pair<P,double> C;
typedef vector<P> Poly;
#define X real()
#define Y imag()
const double EPS = (1e-10);
const double INF = (1e15);
  
namespace std{
  bool operator < (const P& a, const P& b){
    return a.X != b.X ? a.X < b.X : a.Y < b.Y;
  }
  bool operator == (const P& a, const P& b){
    return abs(a-b) < EPS;
  }
}

double dot(P a, P b){
  return a.X * b.X + a.Y * b.Y;
}
double cross(P a, P b){
  return a.X * b.Y - a.Y * b.X;
}

int ccw(P a, P b, P c){
  b -= a;
  c -= a;
  if(cross(b,c) > EPS) return 1;
  if(cross(b,c) < -EPS) return -1;
  if(dot(b,c) < -EPS) return 2;
  if(norm(c) - norm(b) > EPS) return -2;
  return 0;
}

bool is_cross(L a, L b){
  //接しているのはセーフ
  if(ccw(a.first,a.second,b.first)*ccw(a.first,a.second,b.second) < 0 &&
     ccw(b.first,b.second,a.first)*ccw(b.first,b.second,a.second) < 0)
    return true;
  return false;
}

int in_poly(P a, Poly p){
  int n = p.size(), c = 0;
  for(int i = 0; i < n; ++i){
    P s = p[i] - a, t = p[(i+1)%n] - a;
    if(!ccw(s,t,P(0,0))) return 1;//周上
    if(s.Y > t.Y + EPS) swap(s,t);
    if((s.Y*t.Y < 0 || (s.Y*t.Y < EPS && t.Y > EPS)) && cross(s,t) < EPS) ++c;
  }
  if(c%2) return 2;//内部
  return 0;//外
}

using namespace std;
int main(){
  int n;
  while(cin >> n, n){
    Poly V;
    for(int i = 0; i < n; ++i){
      double x, y;
      cin >> x >> y;
      V.push_back(P(x,y));
    }
    vector< vector<bool> > valid(n,vector<bool>(n,false));
    for(int i = 0; i < n; ++i){
      for(int j = 0; j < i; ++j){
        L l = L(V[i], V[j]);
        bool f = false;
        for(int k = 0; k < n; ++k){
          if(k == i || (k+1)%n == i || k == j || (k+1)%n == j) continue;
          f |= is_cross(l, L(V[k], V[(k+1)%n]));
          if(f){
            //cout << "(" << i << ", " << j << "), " << "(" << k << ", " << (k+1)%n << "), " << endl;
            break;
          }
        }
        if(f) continue;
        for(int k = 0; k < n; ++k){
          P m = V[i] + (V[j] - V[i])/(double)(n*k);
          if(!in_poly(m, V)) f = true;
        }
        if(f) continue;
        valid[i][j] = true;
        valid[j][i] = true;
      }
    }
    for(int i = 0; i < n; ++i){
      valid[i][i] = true;
      valid[i][(i+1)%n] = true;
      valid[(i+1)%n][i] = true;
    }
    /*
    for(int i = 0; i < n; ++i){
      for(int j = 0; j < n; ++j) cout << valid[i][j] << " ";cout << endl;
    }
    */
    int ans = n/3;
    for(int i = 1; i < (1<<n); ++i){
      vector<bool> ok(n, false);
      int c = 0;
      for(int j = 0; j < n; ++j){
        if(!((i>>j) & 1)) continue;
        ++c;
        for(int k = 0; k < n; ++k){
          if(valid[j][k] && valid[j][(k+1)%n]) ok[k] = true;
        }
      }
      bool f = true;
      //cout << bitset<8>(i) << endl;
      //for(int j = 0; j < n; ++j) cout << ok[j] << " ";cout << endl;
      for(int j = 0; j < n; ++j) f &= ok[j];
      if(f) ans = min(ans, c);
    }
    cout << ans << endl;
  }
  return 0;
}
accuracy: 0.42857142857142855
time_ms: 30
memory_kb: 3284
final_rank: 18

code_snippet: #include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)n;i++)
#define all(c) (c).begin(),(c).end()
#define pb push_back
#define dbg(...) do{cerr<<__LINE__<<": ";dbgprint(#__VA_ARGS__, __VA_ARGS__);}while(0);

using namespace std;

namespace std{template<class S,class T>struct hash<pair<S,T>>{size_t operator()(const pair<S,T>&p)const{return ((size_t)1e9+7)*hash<S>()(p.first)+hash<T>()(p.second);}};template<class T>struct hash<vector<T>>{size_t operator()(const vector<T> &v)const{size_t h=0;for(auto i : v)h=h*((size_t)1e9+7)+hash<T>()(i)+1;return h;}};}
template<class T>ostream& operator<<(ostream &os, const vector<T> &v){os<<"[ ";rep(i,v.size())os<<v[i]<<(i==v.size()-1?" ]":", ");return os;}template<class T>ostream& operator<<(ostream &os,const set<T> &v){os<<"{ "; for(const auto &i:v)os<<i<<", ";return os<<"}";}
template<class T,class U>ostream& operator<<(ostream &os,const map<T,U> &v){os<<"{";for(const auto &i:v)os<<" "<<i.first<<": "<<i.second<<",";return os<<"}";}template<class T,class U>ostream& operator<<(ostream &os,const pair<T,U> &p){return os<<"("<<p.first<<", "<<p.second<<")";}
void dbgprint(const string &fmt){cerr<<endl;}template<class H,class... T>void dbgprint(const string &fmt,const H &h,const T&... r){cerr<<fmt.substr(0,fmt.find(","))<<"= "<<h<<" ";dbgprint(fmt.substr(fmt.find(",")+1),r...);}
typedef long long ll;typedef vector<int> vi;typedef pair<int,int> pi;const double EPS = 1e-8, INF = 1e12, PI = acos(-1.0);
typedef complex<double> P;
namespace std{
	bool operator<(const P& a, const P& b){
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}
}
inline double cross(const P& a, const P& b){ return imag(conj(a)*b); }
inline double dot(const P& a, const P& b){ return real(conj(a)*b); }
struct L : public vector<P>{
	L(const P &a, const P &b) {
		push_back(a); push_back(b);
	}
};
typedef vector<P> G;
inline int ccw(P a, P b, P 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)+EPS <norm(c)) return -2;      // a--b--c on line
	return 0;                                   // c is between a and b (inclusive)
}
bool intersectLS(const L &l, const L &s) {
  return cross(l[1]-l[0], s[0]-l[0])*       // s[0] is left of l
         cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l
}
bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) < 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) < 0;
}
P crosspoint(const L &l, const L &m) {
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
	if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
	return m[0] + B / A * (m[1] - m[0]);
}
G convex_hull(G ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	G ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
	for (int i = n-2, t = k+1; i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
	ch.resize(k-1);
	return ch;
}
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
double area2(const G& g) {
	double A = 0;
	for (int i = 0; i < g.size(); ++i) 
		A += cross(curr(g, i), next(g, i));
	return A;
}
enum { OUT, ON, IN };
int contains(const G& g, const P& p) {
	bool in = false;
	for (int i = 0; i < g.size(); ++i) {
		P a = curr(g,i) - p, b = next(g,i) - p;
		if (imag(a) > imag(b) + EPS) swap(a, b);
		if (imag(a) < EPS && EPS < imag(b))
		if (cross(a, b) < -EPS) in = !in;
		if (abs(cross(a, b)) < EPS && dot(a, b) < EPS) return ON;
	}
	return in ? IN : OUT;
}

int main(){
	cin.tie(0); cin.sync_with_stdio(0);
	int n;
	while(cin >> n, n){
		G ps;
		rep(i, n){ int x, y; cin >> x >> y; ps.emplace_back(x, y); }
		//各辺を任意の二頂点を結ぶ直線との交点で分割
		vector<G> points;
		rep(i, n){
			G pts = { ps[i], ps[(i + 1) % n] };
			L e(ps[i], ps[(i + 1) % n]);
			rep(j, n) rep(k, j){
				L l(ps[j], ps[k]);
				if(!intersectLS(l, e)) continue;
				pts.pb(crosspoint(l, e));
			}
			sort(all(pts), [&](P a, P b){
				return abs(ps[i] - a) < abs(ps[i] - b);
			});
			//近い点は消す
			rep(j, (int)pts.size() - 1) if(abs(pts[j] - pts[j + 1]) < EPS){
				pts.erase(pts.begin() + j);
				j--;
			}
			//中点を足す
			int sz = (int)pts.size() - 1;
			rep(j, sz) pts.pb((pts[j] + pts[j + 1]) / 2.0);
			sort(all(pts), [&](P a, P b){
				return abs(ps[i] - a) < abs(ps[i] - b);
			});
			swap(pts[1], pts.back());
			points.pb(pts);
		}
		//rep(i, n) dbg(i, points[i]);
		
		vector<vi> flags;
		for(const auto &pts : points){
			vi fs;
			for(const P &p : pts){
				int f = 0;
				rep(i, n){
					L l(p, ps[i]);
					G crs = {l[0], l[1]};
					
					//辺と交差してたらダメ
					rep(j, n){
						L e(ps[j], ps[(j + 1) % n]);
						if(intersectSS(l, e)) goto NG;
					}
					
					//外に出てたらダメ
					rep(j, n) if(ccw(l[0], ps[j], l[1]) == -2) crs.pb(ps[j]);
					sort(all(crs), [&](P a, P b){
						return abs(l[0] - a) < abs(l[0] - b);
					});
					rep(j, (int)crs.size()-1){
						if(contains(ps, (crs[j] + crs[j+1]) / 2.0) == OUT){
							/*
							dbg(crs[j], crs[j+1]);
							dbg((crs[j] + crs[j+1]) / 2.0);
							*/
							goto NG;
						}
					}
					f |= 1 << i;
					NG:;
				}
				fs.pb(f);
			}
			flags.pb(fs);
		}
		
		int ans = (n + 1) / 2;
		rep(mask, 1 << n){
			int sz = __builtin_popcount(mask);
			if(sz >= ans) continue;
			
			for(const vi fs : flags) for(int f : fs) if(!(f & mask)) goto NEXT;
			
			ans = min(ans, sz);
			NEXT:;
		}
		cout << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3304
final_rank: 5

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <utility>
#include <algorithm>
#include <cmath>
#include <bitset>
using namespace std;

#define MAX_PART 512

const double EPS = 1e-10;
const double INF = 1e12;
#define LE(n,m) ((n) < (m) + EPS)
#define GE(n,m) ((n) + EPS > (m))
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : VP{
    L(const P& a, const P& b){ resize(2); at(0)=a; at(1)=b; }
    L(){ resize(2); }
};
namespace std{
    bool operator < (const P& a, const P& b){
        return (a.X!=b.X) ? a.X<b.X : a.Y<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) <-EPS) return -1; //cw
    if(dot(b,c) < EPS) return +2; //c-a-b
    if(norm(b) < norm(c)) return -2; //a-b-c
    return 0; //a-c-b
}
bool intersectSP(const L& s, const P& p){
    return abs(s[0]-p) +abs(s[1]-p) -abs(s[1]-s[0]) < EPS;
}
bool intersectSS(const L& s, const L& t){
    for(int i=0; i<2; i++){
        for(int j=0; j<2; j++){
            if(s[i]==t[j]) return true;
        }
    }
    return ( ccw(s[0],s[1],t[0]) *ccw(s[0],s[1],t[1]) <= 0 ) &&
        ( ccw(t[0],t[1],s[0]) *ccw(t[0],t[1],s[1]) <= 0 );
}
bool intersectLS(const L& l, const L& s){
    return cross(l[1]-l[0], s[0]-l[0])*
        cross(l[1]-l[0], s[1]-l[0]) < EPS;
}
P crosspointLL(const L &l, const L &m) {
    double A = cross(l[1]-l[0], m[1]-m[0]);
    double B = cross(l[1]-l[0], l[1]-m[0]);
    return m[0] + B /A *(m[1]-m[0]);
}

bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}

bool in_poly(const P &p, const VP &poly){
    int n = poly.size();
    int cn=0;
    for(int i=0; i<n; i++){
        if(intersectSP(L(poly[i], poly[(i+1)%n]), p)){
            return true;
        }
    }
    L ray(p, p+P(INF, 0));
    for(int i=0; i<n; i++){
        if((poly[i].Y <= p.Y && poly[(i+1)%n].Y > p.Y) ||
           (poly[i].Y > p.Y && poly[(i+1)%n].Y <= p.Y)){
            if(intersectSS(ray, L(poly[i],poly[(i+1)%n]))){
                cn++;
            }
        }
    }
    return cn%2 != 0;
}

bool isVisible(const L &l, const VP &poly){
    int n = poly.size();
    VP cp;
    for(int i=0; i<n; i++){
        L edge(poly[i], poly[(i+1)%n]);
        if(!isParallel(l, edge) && intersectSS(l, edge)){
            cp.push_back(crosspointLL(l, edge));
        }
    }
    sort(cp.begin(), cp.end());
    
    bool ret = true;
    for(int i=0; i<(int)cp.size()-1; i++){
        if(!in_poly((cp[i]+cp[i+1])/2.0, poly)){
            ret = false;
            break;
        }
    }
    return ret;
}

int bitcount(int n){
    n = (n & 0x55555555) + (n >> 1 & 0x55555555);
    n = (n & 0x33333333) + (n >> 2 & 0x33333333);
    n = (n & 0x0f0f0f0f) + (n >> 4 & 0x0f0f0f0f);
    n = (n & 0x00ff00ff) + (n >> 8 & 0x00ff00ff);
    return (n & 0x0000ffff) + (n >>16 & 0x0000ffff);
}


int main(){
    while(1){
        int n;
        cin >> n;
        if(n==0) break;
    
        VP poly(n);
        for(int i=0; i<n; i++){
            int x,y;
            cin >> x >> y;
            poly[i] = P(x,y);
        }

        //visible graph of vertices
        vector<vector<bool> > vvis(n, vector<bool>(n, false));
        for(int i=0; i<n; i++){
            vvis[i][i] = true;
            for(int j=i+1; j<n; j++){
                L ray(poly[i], poly[j]);
                if(isVisible(ray, poly)){
                    vvis[i][j] = vvis[j][i] = true;
                }
            }
        }

        //vis[i][j]=L(p1, p2);
        //from ith vertex, between p1 and p2 is visible
        vector<vector<L> > vis(n, vector<L>(n));
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                vis[i][j][0] = max(poly[j],poly[(j+1)%n]);
                vis[i][j][1] = min(poly[j],poly[(j+1)%n]);
            }
        }
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                L edge(poly[j], poly[(j+1)%n]);
                if(vvis[i][j] && vvis[i][(j+1)%n]){
                    vis[i][j][0] = min(edge[0], edge[1]);
                    vis[i][j][1] = max(edge[0], edge[1]);
                    continue;
                }
            
                for(int k=0; k<n; k++){
                    if(i==k || !vvis[i][k]) continue;
                    L ray(poly[i], poly[k]);
                    if(isParallel(ray, edge) || !intersectLS(ray, edge)) continue;                
                    P target = crosspointLL(ray, edge);
                    if(abs(poly[i]-target) < abs(poly[k]-target)) continue;
                    if(isVisible(L(poly[k], target), poly)){
                        vis[i][j][0] = min(vis[i][j][0], target);
                        vis[i][j][1] = max(vis[i][j][1], target);
                    }
                }
            }
        }

        vector<vector<P> > cut(n);
        for(int i=0; i<n; i++){ //edge
            for(int j=0; j<n; j++){
                cut[i].push_back(vis[j][i][0]);
                cut[i].push_back(vis[j][i][1]);
            }
            sort(cut[i].begin(), cut[i].end());
            cut[i].erase(unique(cut[i].begin(), cut[i].end()), cut[i].end());
        }
        
        vector<bitset<MAX_PART> > cover(n);
        int offset=0;
        for(int i=0; i<n; i++){ //edge
            for(int j=0; j<n; j++){ //vertex
                if(vis[j][i][0] < vis[j][i][1]){                    
                    int s=0,e=0;
                    for(int k=0; k<(int)cut[i].size(); k++){
                        if(vis[j][i][0] == cut[i][k]){
                            s = k;
                        }
                        if(vis[j][i][1] == cut[i][k]){
                            e = k;
                            break;

                        }
                    }
                    for(int k=s; k<e; k++){
                        cover[j][offset+k] = 1;
                    }
                }
            }
            offset += cut[i].size() -1;
        }
        
        bitset<MAX_PART> allbits;
        for(int i=0; i<offset; i++) allbits[i]=1;

        //brute force
        int ans = (n+1)/2; //obvious upper bound
        for(int i=0; i<(1<<n); i++){
            if(bitcount(i) > ans) continue;
            bitset<MAX_PART> tmp;
            for(int j=0; j<n; j++){
                if((i&(1<<j)) != 0){
                    tmp |= cover[j];
                }
            }
            if(tmp == allbits){
                ans = bitcount(i);
            }
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3196
final_rank: 2

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <utility>
#include <algorithm>
#include <cmath>
#include <bitset>
using namespace std;

#define MAX_PART 512

const double EPS = 1e-10;
const double INF = 1e12;
#define LE(n,m) ((n) < (m) + EPS)
#define GE(n,m) ((n) + EPS > (m))
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : VP{
    L(const P& a, const P& b){ resize(2); at(0)=a; at(1)=b; }
    L(){ resize(2); }
};
namespace std{
    bool operator < (const P& a, const P& b){
        return (a.X!=b.X) ? a.X<b.X : a.Y<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) <-EPS) return -1; //cw
    if(dot(b,c) < EPS) return +2; //c-a-b
    if(norm(b) < norm(c)) return -2; //a-b-c
    return 0; //a-c-b
}
bool sameLL(const L &l, const L &m) {
    return ( abs(cross(l[1]-l[0], m[0]-l[0])) < EPS ) &&
        ( abs(cross(l[1]-l[0], m[0]-l[0])) < EPS );
}
bool intersectSP(const L& s, const P& p){
    return abs(s[0]-p) +abs(s[1]-p) -abs(s[1]-s[0]) < EPS;
}
bool intersectSS(const L& s, const L& t){
    for(int i=0; i<2; i++){
        for(int j=0; j<2; j++){
            if(s[i]==t[j]) return true;
        }
    }
    return ( ccw(s[0],s[1],t[0]) *ccw(s[0],s[1],t[1]) <= 0 ) &&
        ( ccw(t[0],t[1],s[0]) *ccw(t[0],t[1],s[1]) <= 0 );
}
bool intersectLS(const L& l, const L& s){
    return cross(l[1]-l[0], s[0]-l[0])*
        cross(l[1]-l[0], s[1]-l[0]) < EPS;
}
P crosspointLL(const L &l, const L &m) {
    double A = cross(l[1]-l[0], m[1]-m[0]);
    double B = cross(l[1]-l[0], l[1]-m[0]);
    return m[0] + B /A *(m[1]-m[0]);
}

bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}

//???????¨?
bool in_poly(const P &p, const VP &poly){
    int n = poly.size();
    int cn=0;
    //??????????????????true
    for(int i=0; i<n; i++){
        if(intersectSP(L(poly[i], poly[(i+1)%n]), p)){
            return true;
        }
    }
    L ray(p, p+P(INF, 0));
    for(int i=0; i<n; i++){
        if((poly[i].Y <= p.Y && poly[(i+1)%n].Y > p.Y) ||
           (poly[i].Y > p.Y && poly[(i+1)%n].Y <= p.Y)){
            if(intersectSS(ray, L(poly[i],poly[(i+1)%n]))){
                cn++;
            }
        }
    }
    return cn%2 != 0;
}

//???????¨?
//l????????????????§???¢???????????????????????¨??§???????????¨???????????????
bool isVisible(const L &l, const VP &poly){
    int n = poly.size();
    VP cp;
    for(int i=0; i<n; i++){
        L edge(poly[i], poly[(i+1)%n]);
        if(!isParallel(l, edge) && intersectSS(l, edge)){
            cp.push_back(crosspointLL(l, edge));
        }
    }
    sort(cp.begin(), cp.end());
    
    bool ret = true;
    for(int i=0; i<(int)cp.size()-1; i++){
        //???????????????????????????????????????????????§????§???¢?????¨???????????????ok
        if(!in_poly((cp[i]+cp[i+1])/2.0, poly)){
            ret = false;
            break;
        }
    }
    return ret;
}

int bitcount(int n){
    n = (n & 0x55555555) + (n >> 1 & 0x55555555);
    n = (n & 0x33333333) + (n >> 2 & 0x33333333);
    n = (n & 0x0f0f0f0f) + (n >> 4 & 0x0f0f0f0f);
    n = (n & 0x00ff00ff) + (n >> 8 & 0x00ff00ff);
    return (n & 0x0000ffff) + (n >>16 & 0x0000ffff);
}


int main(){
    while(1){
        int n;
        cin >> n;
        if(n==0) break;
    
        VP poly(n);
        for(int i=0; i<n; i++){
            int x,y;
            cin >> x >> y;
            poly[i] = P(x,y);
        }


        //???????????????????????°???????????????
        vector<vector<bool> > vvis(n, vector<bool>(n, false));
        for(int i=0; i<n; i++){
            vvis[i][i] = true;
            for(int j=i+1; j<n; j++){
                L ray(poly[i], poly[j]);
                if(isVisible(ray, poly)){
                    vvis[i][j] = vvis[j][i] = true;
                }
            }
        }

        //cout << intersectSS(L(poly[0], poly[6]), L(poly[0], poly[1])) << endl;
        
        //????????§???????????????
        /*
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                cerr << vvis[i][j] << " ";
            }
            cerr << endl;
        }
        cerr << endl;
        continue;
        */

        

        //vis[i][j]????§????
        //vis[i][j]=L(p1, p2);
        //i????????????????????????j???????????????p1??????p2???????????????????????????
        vector<vector<L> > vis(n, vector<L>(n));
        //?????????
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                vis[i][j][0] = max(poly[j],poly[(j+1)%n]);
                vis[i][j][1] = min(poly[j],poly[(j+1)%n]);
            }
        }
    
        //i?????????????????????j???????????????
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                L edge(poly[j], poly[(j+1)%n]);
                //??????????????????????????????????°????????????????
                if(vvis[i][j] && vvis[i][(j+1)%n]){
                    vis[i][j][0] = min(edge[0], edge[1]);
                    vis[i][j][1] = max(edge[0], edge[1]);
                    continue;
                }
            
                //?????´???i-k????????????
                for(int k=0; k<n; k++){
                    if(i==k || !vvis[i][k]) continue;
                    L ray(poly[i], poly[k]);
                    //????¨??¨????
                    if(isParallel(ray, edge) || !intersectLS(ray, edge)) continue;
                
                    P target = crosspointLL(ray, edge);
                    //?????´?????????(i->k?????¶???????????§????????£??????)
                    if(abs(poly[i]-target) < abs(poly[k]-target)) continue;

                    if(isVisible(L(poly[k], target), poly)){
                        vis[i][j][0] = min(vis[i][j][0], target);
                        vis[i][j][1] = max(vis[i][j][1], target);
                    }
                }
            }
        }
        //????????§???????????????
        /*
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                cerr << vis[i][j][0] << " " << vis[i][j][1] << endl;
            }
            cerr << endl;
        }
        cerr << endl;
        continue;
        */
    
        //???????????¨?????????????????????
        //???????????????????????°??????????????????????????§?????????????????¨?????????bitset???
        vector<vector<P> > cut(n);
        for(int i=0; i<n; i++){ //???i????????????
            //L edge(poly[i], poly[(i+1)%n]);
            for(int j=0; j<n; j++){
                cut[i].push_back(vis[j][i][0]);
                cut[i].push_back(vis[j][i][1]);
            }
            sort(cut[i].begin(), cut[i].end());
            cut[i].erase(unique(cut[i].begin(), cut[i].end()), cut[i].end());
        }

        //?????????
        /*
        for(int i=0; i<n; i++){
            cout << cut[i].size() << endl;
            for(int j=0; j<(int)cut[i].size(); j++){
                cout << cut[i][j] << endl;
            }
        }
        continue;
        */

        
        vector<bitset<MAX_PART> > cover(n);
        int offset=0;
        for(int i=0; i<n; i++){ //???i????????????
            for(int j=0; j<n; j++){ //??????j????????????
                if(vis[j][i][0] < vis[j][i][1]){                    
                    int s=0,e=0;
                    for(int k=0; k<(int)cut[i].size(); k++){
                        if(vis[j][i][0] == cut[i][k]){
                            s = k;
                        }
                        if(vis[j][i][1] == cut[i][k]){
                            e = k;
                            break;

                        }
                    }
                    for(int k=s; k<e; k++){
                        cover[j][offset+k] = 1;
                    }
                }
            }
            offset += cut[i].size() -1;
        }

        //?????????
        /*
        for(int i=0; i<n; i++){
            int offset = 0;
            for(int k=0; k<n; k++){
                for(int j=0; j<(int)cut[k].size()-1; j++){
                    cout << cover[i][offset+j] << " ";
                }
                offset += cut[k].size()-1;
                cout << " | ";
            }
            cout << endl;
        }
        continue;
        */
        
        bitset<MAX_PART> allbits;
        for(int i=0; i<offset; i++) allbits[i]=1;

        //???????????§?????????????????¨??¢?´¢
        int ans = (n+1)/2; //????????????????¨????????????°??????????????¶????????????
        for(int i=0; i<(1<<n); i++){
            //?????????????????£??????????????°???ans??\???????????°????????????
            if(bitcount(i) > ans) continue;
            bitset<MAX_PART> tmp;
            //?????????????????£???????????¨????????§???????????????
            for(int j=0; j<n; j++){
                if((i&(1<<j)) != 0){
                    tmp |= cover[j];
                }
            }
            //????????¨?????????????????§????????????????????°ans?????´??°
            if(tmp == allbits){
                ans = bitcount(i);
            }
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3184
final_rank: 1

code_snippet: #include<bits/stdc++.h>

using namespace std;
#define rep(i, n) for ( int i = 0; i < (int)n; i++ )
#define EPS (1e-8)
#define equals(a, b) (fabs((a) - (b)) < EPS )
#define dle(a, b) (equals(a, b) || a < b )
typedef pair<int, pair<int, int> > Triple;

static const double PI = acos(-1);

class Point{
    public:
    double x, y;
    Point (double x = 0, double y = 0): x(x), y(y){ }

    Point operator + ( Point p ){ return Point(x + p.x, y + p.y); }
    Point operator - ( Point p ){ return Point(x - p.x, y - p.y); }
    Point operator * ( double a ){ return Point(x*a, y*a); }
    Point operator / ( double a ){ return Point(x/a, y/a); }

    double abs() { return sqrt(norm());}
    double norm() { return x*x + y*y; }

    bool operator < ( const Point &p ) const {return x != p.x ? x < p.x : y < p.y;}
    bool operator == ( const Point &p ) const { return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;}
};

typedef Point Vector;

class Segment{
    public:
    Point p1, p2;
    Segment(Point s = Point(), Point t = Point()): p1(s), p2(t){}
};

class SegmentSet{
    public:
    Point p1, p2;
    vector<Point> in;
    vector<int> v;
    SegmentSet(Point s = Point(), Point t = Point()): p1(s), p2(t){}
    void addIntermediate(Point p){ in.push_back(p); }
    void normalize(){
    in.push_back(p1);
    in.push_back(p2);
    sort(in.begin(), in.end());
    vector<Point>::iterator end_it = unique(in.begin(), in.end());
    in.erase(end_it, in.end());
    v.resize(in.size());
    }
    void reset(){
    for ( int i = 0; i < v.size(); i++ ) v[i] = 0;
    }
    bool valid(){
    for ( int i = 0; i < v.size()-1; i++ ) if ( !v[i]) return false;
    return true;
    }
    void print(){
    for ( int i = 0; i < in.size(); i++ ){
        cout << in[i].x << "," << in[i].y << endl;
    }
    }
};

typedef Segment Line;
typedef vector<Point> Polygon;

double norm( Vector a ){ return a.x*a.x + a.y*a.y; }
double abs( Vector a ){ return sqrt(norm(a)); }
Point polar( double a, double r ){ return Point(cos(r)*a, sin(r)*a);}
double getDistance( Vector a, Vector b ){ return abs(a - b); }
double dot( Vector a, Vector b ){ return a.x*b.x + a.y*b.y; }
double cross( Vector a, Vector b ){ return a.x*b.y - a.y*b.x; }
double arg(Vector p){ return atan2(p.y, p.x); }

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw( Point p0, Point p1, Point p2 ){
    Vector a = p1 - p0;
    Vector b = p2 - p0;
    if ( cross(a, b) > EPS ) return COUNTER_CLOCKWISE;
    if ( cross(a, b) < -EPS ) return CLOCKWISE;
    if ( dot(a, b) < -EPS ) return ONLINE_BACK;
    if ( norm(a) < norm(b) ) return ONLINE_FRONT;
    return ON_SEGMENT;
}
bool isIntersect(Point p1, Point p2, Point p3, Point p4){
    return ( ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
         ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0 );
}

bool isIntersect(Segment s1, Segment s2){
    return isIntersect(s1.p1, s1.p2, s2.p1, s2.p2);
}

bool isParallel( Vector a, Vector b ){
    return equals( cross(a, b), 0.0 );
}

bool isParallel( Point a1, Point a2, Point b1, Point b2){
    return isParallel( a1 - a2, b1 - b2 );
}

bool isParallel( Segment s1, Segment s2){
  return isParallel( s1.p1, s1.p2, s2.p1, s2.p2);
}

Point getCrossPoint(Segment s1, Segment s2){
    assert( isIntersect(s1, s2) );
    Vector base = s2.p2 - s2.p1;
    double d1 = abs(cross(base, s1.p1 - s2.p1));
    double d2 = abs(cross(base, s1.p2 - s2.p1));
    double t = d1/(d1 + d2);
    return s1.p1 + (s1.p2 - s1.p1)*t;
}

Point getCrossPointLines( Line s1, Line s2){
    Vector a = s1.p2 - s1.p1;
    Vector base = s2.p2 - s2.p1;
    return s1.p1 + a * cross(base, s2.p1 - s1.p1)/cross(base, a);
}
// angle p1 -> p0 -> p2;
double getAngle(Point p0, Point p1, Point p2){
  if ( !(ccw(p0, p1, p2) == CLOCKWISE || ccw(p0, p1, p2) == COUNTER_CLOCKWISE )) return 0;
  double b = abs(p1 - p0);
  double c = abs(p2 - p0);
  double a = abs(p1 - p2);
  double r = acos((b*b+c*c-a*a)/(2*b*c));
  if ( ccw(p0, p1, p2) == CLOCKWISE ) r *= -1;
  return r;
}

bool insidePolygon(Polygon g, Point t){
  double angle = 0.0;
  rep(i, g.size()){
    Point p1 = g[i];
    Point p2 = g[(i+1)%g.size()];
    if ( ccw(p1, p2, t) == ON_SEGMENT ) return true;
    angle += getAngle(t, p1, p2);
  }
  return equals(2*acos(-1), fabs(angle) );
}

bool insidePolygonSegment(Polygon g, Segment s){
  if ( !insidePolygon(g, s.p1) || !insidePolygon(g, s.p2) ) return false;
  vector<Point> pointInSeg;
  pointInSeg.push_back(s.p1);
  pointInSeg.push_back(s.p2);
  for ( int i = 0; i < g.size(); i++ ){
    Segment ps = Segment(g[i], g[(i+1)%g.size()]);
    if ( isParallel(ps, s) ) continue;
    if ( !isIntersect(ps, s) ) continue;
    Point x = getCrossPoint(ps, s);
    if ( !(x == s.p1 || x == s.p2 || x == ps.p1 || x == ps.p2 ) ) return false;
    pointInSeg.push_back(x);
  }
  sort(pointInSeg.begin(), pointInSeg.end());
  for ( int i = 0; i < pointInSeg.size()-1; i++ ){
    Point s = pointInSeg[i];
    Point t = pointInSeg[i+1];
    Point c = Point((s.x+t.x)/2, (s.y+t.y)/2);
    if ( !insidePolygon(g, c) ) return false;
  }
  return true;
}

bool isPolygonIntersect(Polygon g1, Polygon g2){
    rep(i, g1.size()) rep(j, g2.size()) {
    if ( isIntersect(g1[i], g1[(i+1)%g1.size()],
             g2[j], g2[(j+1)%g2.size()])) return true;
    }
    rep(i, g1.size())  if ( insidePolygon(g2, g1[i]) ) return true;
    rep(i, g2.size())  if ( insidePolygon(g1, g2[i]) ) return true;
    return false;
}
bool isOnline(Point p1, Point p2, Point p3, Point p4){
    int c1 = ccw(p1, p2, p3);
    int c2 = ccw(p1, p2, p4);
    if ( c1 < 0 ) c1 *= -1;
    if ( c2 < 0 ) c2 *= -1;
    return c1 != 1 && c2 != 1;
}
bool included(Point p1, Point p2, Point p3, Point p4){
    return ccw(p3, p4, p1) == ON_SEGMENT && ccw(p3, p4, p2) == ON_SEGMENT;
}
// p1-p2 is the base
bool isInsideTriangle(Point p1, Point p2, Point p3, Polygon &g){
    assert( !(p1==p2));
    if ( !insidePolygonSegment(g, Segment(p1, p2)) ) return false;
    if ( !insidePolygonSegment(g, Segment(p1, p3)) ) return false;
    if ( !insidePolygonSegment(g, Segment(p2, p3)) ) return false;
    return true;
}

bool segmentVisible(Point p1, Point p2, bool used[], Polygon &g){
    for ( int i = 0; i < g.size(); i++ ){
    if ( !used[i] ) continue;
    if ( isInsideTriangle(p1, p2, g[i], g) ) return true;
    }
    return false;
}

bool visible(bool used[], vector<SegmentSet> &S, Polygon &g, vector<vector<pair<int, int> > > &C){
    for ( int i = 0; i < S.size(); i++ ) S[i].reset();
    for ( int i = 0; i < g.size(); i++ ){
    if ( !used[i] ) continue;
    for ( int k = 0; k < C[i].size(); k++ ){
        pair<int, int> p = C[i][k];
        S[p.first].v[p.second] = 1;
    }
    }
    for ( int i = 0; i < S.size(); i++ ) if ( !S[i].valid() ) return false;
    return true;
}

void rec(int pos, int cnt, vector<SegmentSet> &S, bool used[], int &minv, Polygon &g, vector<vector<pair<int, int> > > &C){
    if ( cnt > minv ) return;
    if ( pos == g.size() ){
    if ( visible(used, S, g, C) ) minv = min(minv, cnt);
    return;
    }
    rec(pos+1, cnt, S, used, minv, g, C);
    used[pos] = true;
    rec(pos+1, cnt+1, S, used, minv, g, C);
    used[pos] = false;
}

void compute(Polygon g){
    vector<SegmentSet> S;
    rep(i, g.size()) S.push_back(SegmentSet(g[i], g[(i+1)%g.size()]));
    for ( int i = 0; i < g.size()-1; i++ ){
    for ( int j = i+1; j < g.size(); j++ ){
        if ( g[i] == g[j] ) continue;
        Line base = Line(g[i], g[j]);
        for ( int k = 0; k < S.size(); k++ ){
        if ( isParallel(base.p1, base.p2, S[k].p1, S[k].p2) ) continue;
        Point x = getCrossPointLines(Line(base.p1, base.p2), Line(S[k].p1, S[k].p2));
        if ( ccw(S[k].p1, S[k].p2, x) == ON_SEGMENT) S[k].addIntermediate(x);
        }
    }
    }
    for ( int i = 0; i < S.size(); i++ ) S[i].normalize();

    vector<vector<pair<int, int> > > C;
    C.resize(g.size());

    for ( int i = 0; i < S.size(); i++ ){
    for ( int j = 0; j < S[i].in.size()-1; j++ ){
        for ( int k = 0; k < g.size(); k++ ){
        Point p1 = S[i].in[j];
        Point p2 = S[i].in[j+1];
        if ( isInsideTriangle(p1, p2, g[k], g) ) {
            C[k].push_back(make_pair(i, j));
        }
        }
    }
    }

    bool used[20];
    int minv = g.size();
    rep(i, S.size()) used[i] = false;
    rec(0, 0, S, used, minv, g, C);
    cout << minv << endl;
}

int main(){
  int x, y;
  int n;
  int tcase = 0;
  while(1){
    cin >> n;
    if ( n == 0 ) break;
    Polygon g;
    rep(i, n){
      cin >> x >> y;
      g.push_back(Point(x, y));
    }
    compute(g);
  }
}
accuracy: 1
time_ms: 190
memory_kb: 3480
final_rank: 7

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
const ld eps = 1e-9;

typedef ld  Weight;
struct Edge {
	int src, dest;
	int cap, rev;
	Weight weight;
	bool operator < (const Edge &rhs) const { return weight > rhs.weight; }
};


/* ??????????????¬ */

#include <complex>

typedef complex<ld> Point;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(x) (x).begin(),(x).end()


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
	bool operator==(const Point &lhs, const Point &rhs) {
		return abs(rhs - lhs) < eps;
	}
	bool operator!=(const Point &lhs, const Point &rhs) {
		return abs(rhs - lhs) > eps;
	}
}

// ????????\???
Point input_Point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// ????????????????????????
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// ??????
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// ??????
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// ??´????????????
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// ????????????
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// ccw
// 1: a,b,c??????????¨???¨?????????????????¶
//-1: a,b,c???????¨???¨?????????????????¶
// 2: c,a,b???????????´???????????¶
//-2: a,b,c???????????´???????????¶
// 0: a,c,b???????????´???????????¶
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,c??????????¨???¨?????????????????¶
	if (cross(nb, nc) < -eps) return -1; // a,b,c???????¨???¨?????????????????¶
	if (dot(nb, nc) < 0) return 2;       // c,a,b???????????´???????????¶
	if (norm(nb) < norm(nc)) return -2;  // a,b,c???????????´???????????¶
	return 0;                          // a,c,b???????????´???????????¶
}


/* ???????????? */

// ??´?????¨??´??????????????????
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// ??´?????¨?????????????????????
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// ????????¨?????????????????????
bool isis_ss(const Line& s, const Line& t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
		ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

// ????????´????????????
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// ?????????????????????
bool isis_sp(const Line& s, const Point& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// ??????????¶?
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.b - l.a) / norm(l.a - l.b);
	return l.a + t * (l.b - l.a);
}

//???????±??????????????????????
Point reflect(const Line &l, const Point &p) {
	Point pr = proj(l, p);
	return pr * 2.l - p;
}

// ??´?????¨??´????????????
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// ??´?????¨??´????????????
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// ????????¨???????????????
//???????????£????????¨???????????¨assert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//??????isis_ss?????????
		assert(false);
		return Point(0, 0);
	}
}
// ????????¨???????????????
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// ??´?????¨???????????¢
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

//??´?????¨??´???????????¢
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// ??´?????¨??????????????¢
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// ????????¨???????????¢
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// ????????¨??????????????¢
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//??´?????¨??´?????????????????????????????????
Line bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}


//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:??????
//c:????????§??????
//???????????´?????????????????¢?????????????±??????????
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* ??? */

// ?????¨????????????
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

//???????????????????????????
/*  0 => out
1 => on
2 => in*/
int is_in_Circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
//???lc??????rc??????????????????
/*0 => out
1 => on
2 => in*/
int Circle_in_Circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// ?????¨??´????????????
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// ?????¨??????????????¢
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// ?????¨????????\???
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// ?????¨????????\???
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), all(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//??????????????????????????¢???
ld two_Circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* ????§???¢ */

typedef vector<Point> Polygon;

// ??¢???
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	rep(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

//????§???¢????????¢??????
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// ??????????????????
/*0 => out
1 => on
2 => in*/
int is_in_Polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//??????????????????2?????????
enum { out, on, in };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// ??????
//???????????????????????¨????????????????????§??¨???
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



//????????????
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon q;
	Polygon r;
	rep(i, n) {
		Point a = ps[i], b = ps[(i + 1) % n];
		Line m = Line(a, b);
		if (ccw(l.a, l.b, a) != -1) q.push_back(a);
		if (ccw(l.a, l.b, a) != 1) r.push_back(a);
		if (ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0 && isis_ll(l, m)) {
			q.push_back(is_ll(l, m));
			r.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ q,r };
	return polys;
}


int main() {
	while (1) {
		int N; cin >> N;
		if (!N)break;
		Polygon poly;
		for (int i = 0; i < N; ++i) {
			int x, y; cin >> x >> y;
			poly.push_back(Point(x, y));
		}
		vector<Point>sects(poly);
		for (int i = 0; i < N; ++i) {
			Line l1(poly[i], poly[(i + 1) % N]);
			for (int j = 0; j < N; ++j) {
				Line l2(poly[j], poly[(j + 1) % N]);
				auto ps = is_ll2(l1, l2);
				if (ps.size() == 1) {
					if (isis_sp(l1, ps[0])) {

						sects.push_back(ps[0]);
					}
				}
			}
		}
		sort(sects.begin(), sects.end());
		sects.erase(unique(sects.begin(), sects.end()), sects.end());
		{
			vector<Point>nextsects(sects);
			for (int i = 0; i < sects.size(); ++i) {
				for (int j = 0; j < sects.size(); ++j) {
					Point p((sects[i] + sects[j]) / 2.l);
					bool ok = false;
					for (int k = 0; k < N; ++k) {
						Line l(poly[k], poly[(k + 1) % N]);
						if (isis_sp(l, p))ok = true;
					}
					if (ok)nextsects.emplace_back(p);
				}
			}
			sects = nextsects;
		}
		sort(sects.begin(), sects.end());
		sects.erase(unique(sects.begin(), sects.end()), sects.end());
		
		vector<vector<int>>oks(N, vector<int>(sects.size()));
		for (int i = 0; i < N; ++i) {
			//Line l1(poly[i], poly[(i + 1) % N]);
			//Line l2(poly[i], poly[(i + N - 1) % N]);
			for (int j = 0; j < sects.size(); ++j) {
				Line l(poly[i], sects[j]);
				bool ok = true;
				vector<Point>aps;
				for (int k = 0; k < N; ++k) {
					Line edge(poly[k], poly[(k + 1) % N]);
					if (abs(cross(edge.b - edge.a, l.b - l.a))<eps) {

					}
					else if(isis_ss(l,edge)){
						Point p(is_ll(l, edge));
						aps.emplace_back(p);
					}
				}
				sort(aps.begin(), aps.end());
				
				for (int k = 0; k < int(aps.size()) - 1; ++k) {
					if (!is_in_Polygon(poly, (aps[k] + aps[k + 1]) / (2.l))) {
						ok = false;
					}
				}
				oks[i][j] = ok;
			}
		}
		int ans = 16;
		for (int i = 0; i < (1 << N); ++i) {
			bitset<16>bs(i);
			vector<int>cats(sects.size());
			for (int j = 0; j < N; ++j) {
				if (bs[j]) {
					for (int k = 0; k < sects.size(); ++k) {
						cats[k] |= oks[j][k];
					}
				}
			}
			if (count(cats.begin(), cats.end(), 0) == 0)ans = min(ans,int( bs.count()));
		}
		cout << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 450
memory_kb: 3244
final_rank: 3

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
const ld eps = 1e-9;

typedef ld  Weight;
struct Edge {
	int src, dest;
	int cap, rev;
	Weight weight;
	bool operator < (const Edge &rhs) const { return weight > rhs.weight; }
};


/* ??????????????¬ */

#include <complex>

typedef complex<ld> Point;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(x) (x).begin(),(x).end()


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
	bool operator==(const Point &lhs, const Point &rhs) {
		return abs(rhs - lhs) < eps;
	}
	bool operator!=(const Point &lhs, const Point &rhs) {
		return abs(rhs - lhs) > eps;
	}
}

// ????????\???
Point input_Point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// ????????????????????????
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// ??????
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// ??????
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// ??´????????????
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// ????????????
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// ccw
// 1: a,b,c??????????¨???¨?????????????????¶
//-1: a,b,c???????¨???¨?????????????????¶
// 2: c,a,b???????????´???????????¶
//-2: a,b,c???????????´???????????¶
// 0: a,c,b???????????´???????????¶
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,c??????????¨???¨?????????????????¶
	if (cross(nb, nc) < -eps) return -1; // a,b,c???????¨???¨?????????????????¶
	if (dot(nb, nc) < 0) return 2;       // c,a,b???????????´???????????¶
	if (norm(nb) < norm(nc)) return -2;  // a,b,c???????????´???????????¶
	return 0;                          // a,c,b???????????´???????????¶
}


/* ???????????? */

// ??´?????¨??´??????????????????
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// ??´?????¨?????????????????????
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// ????????¨?????????????????????
bool isis_ss(const Line& s, const Line& t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
		ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

// ????????´????????????
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// ?????????????????????
bool isis_sp(const Line& s, const Point& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// ??????????¶?
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.b - l.a) / norm(l.a - l.b);
	return l.a + t * (l.b - l.a);
}

//???????±??????????????????????
Point reflect(const Line &l, const Point &p) {
	Point pr = proj(l, p);
	return pr * 2.l - p;
}

// ??´?????¨??´????????????
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// ??´?????¨??´????????????
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// ????????¨???????????????
//???????????£????????¨???????????¨assert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//??????isis_ss?????????
		assert(false);
		return Point(0, 0);
	}
}
// ????????¨???????????????
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// ??´?????¨???????????¢
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

//??´?????¨??´???????????¢
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// ??´?????¨??????????????¢
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// ????????¨???????????¢
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// ????????¨??????????????¢
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//??´?????¨??´?????????????????????????????????
Line bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}


//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:??????
//c:????????§??????
//???????????´?????????????????¢?????????????±??????????
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* ??? */

// ?????¨????????????
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

//???????????????????????????
/*  0 => out
1 => on
2 => in*/
int is_in_Circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
//???lc??????rc??????????????????
/*0 => out
1 => on
2 => in*/
int Circle_in_Circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// ?????¨??´????????????
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// ?????¨??????????????¢
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// ?????¨????????\???
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// ?????¨????????\???
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), all(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//??????????????????????????¢???
ld two_Circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* ????§???¢ */

typedef vector<Point> Polygon;

// ??¢???
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	rep(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

//????§???¢????????¢??????
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// ??????????????????
/*0 => out
1 => on
2 => in*/
int is_in_Polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//??????????????????2?????????
enum { out, on, in };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// ??????
//???????????????????????¨????????????????????§??¨???
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



//????????????
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon q;
	Polygon r;
	rep(i, n) {
		Point a = ps[i], b = ps[(i + 1) % n];
		Line m = Line(a, b);
		if (ccw(l.a, l.b, a) != -1) q.push_back(a);
		if (ccw(l.a, l.b, a) != 1) r.push_back(a);
		if (ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0 && isis_ll(l, m)) {
			q.push_back(is_ll(l, m));
			r.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ q,r };
	return polys;
}


int main() {
	while (1) {
		int N; cin >> N;
		if (!N)break;
		Polygon poly;
		for (int i = 0; i < N; ++i) {
			int x, y; cin >> x >> y;
			poly.push_back(Point(x, y));
		}
		vector<Point>sects(poly);
		for (int i = 0; i < N; ++i) {
			Line l1(poly[i], poly[(i + 1) % N]);
			for (int j = 0; j < N; ++j) {
				Line l2(poly[j], poly[(j + 1) % N]);
				auto ps = is_ll2(l1, l2);
				if (ps.size() == 1) {
					if (isis_sp(l1, ps[0])) {

						sects.push_back(ps[0]);
					}
				}
			}
		}
		vector<vector<int>>oks(N, vector<int>(sects.size()));
		for (int i = 0; i < N; ++i) {
			//Line l1(poly[i], poly[(i + 1) % N]);
			//Line l2(poly[i], poly[(i + N - 1) % N]);
			for (int j = 0; j < sects.size(); ++j) {
				Line l(poly[i], sects[j]);
				bool ok = true;
				vector<Point>aps;
				for (int k = 0; k < N; ++k) {
					Line edge(poly[k], poly[(k + 1) % N]);
					if (abs(cross(edge.b - edge.a, l.b - l.a))<eps) {

					}
					else if(isis_ss(l,edge)){
						Point p(is_ll(l, edge));
						aps.emplace_back(p);
					}
				}
				sort(aps.begin(), aps.end());
				
				for (int k = 0; k < int(aps.size()) - 1; ++k) {
					if (!is_in_Polygon(poly, (aps[k] + aps[k + 1]) / (2.l))) {
						ok = false;
					}
				}
				oks[i][j] = ok;
			}
		}
		int ans = 16;
		for (int i = 0; i < (1 << N); ++i) {
			bitset<16>bs(i);
			vector<int>cats(sects.size());
			for (int j = 0; j < N; ++j) {
				if (bs[j]) {
					for (int k = 0; k < sects.size(); ++k) {
						cats[k] |= oks[j][k];
					}
				}
			}
			if (count(cats.begin(), cats.end(), 0) == 0)ans = min(ans,int( bs.count()));
		}
		cout << ans << endl;
	}
	return 0;
}
accuracy: 0.42857142857142855
time_ms: 110
memory_kb: 3244
final_rank: 14

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
const ld eps = 1e-9;

typedef ld  Weight;
struct Edge {
	int src, dest;
	int cap, rev;
	Weight weight;
	bool operator < (const Edge &rhs) const { return weight > rhs.weight; }
};


/* ??????????????¬ */

#include <complex>

typedef complex<ld> Point;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(x) (x).begin(),(x).end()


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
	bool operator==(const Point &lhs, const Point &rhs) {
		return abs(rhs - lhs) < eps;
	}
	bool operator!=(const Point &lhs, const Point &rhs) {
		return abs(rhs - lhs) > eps;
	}
}

// ????????\???
Point input_Point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// ????????????????????????
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// ??????
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// ??????
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// ??´????????????
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// ????????????
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// ccw
// 1: a,b,c??????????¨???¨?????????????????¶
//-1: a,b,c???????¨???¨?????????????????¶
// 2: c,a,b???????????´???????????¶
//-2: a,b,c???????????´???????????¶
// 0: a,c,b???????????´???????????¶
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,c??????????¨???¨?????????????????¶
	if (cross(nb, nc) < -eps) return -1; // a,b,c???????¨???¨?????????????????¶
	if (dot(nb, nc) < 0) return 2;       // c,a,b???????????´???????????¶
	if (norm(nb) < norm(nc)) return -2;  // a,b,c???????????´???????????¶
	return 0;                          // a,c,b???????????´???????????¶
}


/* ???????????? */

// ??´?????¨??´??????????????????
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// ??´?????¨?????????????????????
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// ????????¨?????????????????????
bool isis_ss(const Line& s, const Line& t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
		ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

// ????????´????????????
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// ?????????????????????
bool isis_sp(const Line& s, const Point& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// ??????????¶?
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.b - l.a) / norm(l.a - l.b);
	return l.a + t * (l.b - l.a);
}

//???????±??????????????????????
Point reflect(const Line &l, const Point &p) {
	Point pr = proj(l, p);
	return pr * 2.l - p;
}

// ??´?????¨??´????????????
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// ??´?????¨??´????????????
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// ????????¨???????????????
//???????????£????????¨???????????¨assert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//??????isis_ss?????????
		assert(false);
		return Point(0, 0);
	}
}
// ????????¨???????????????
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// ??´?????¨???????????¢
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

//??´?????¨??´???????????¢
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// ??´?????¨??????????????¢
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// ????????¨???????????¢
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// ????????¨??????????????¢
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//??´?????¨??´?????????????????????????????????
Line bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}


//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:??????
//c:????????§??????
//???????????´?????????????????¢?????????????±??????????
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* ??? */

// ?????¨????????????
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

//???????????????????????????
/*  0 => out
1 => on
2 => in*/
int is_in_Circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
//???lc??????rc??????????????????
/*0 => out
1 => on
2 => in*/
int Circle_in_Circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// ?????¨??´????????????
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// ?????¨??????????????¢
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// ?????¨????????\???
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// ?????¨????????\???
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), all(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//??????????????????????????¢???
ld two_Circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* ????§???¢ */

typedef vector<Point> Polygon;

// ??¢???
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	rep(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

//????§???¢????????¢??????
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// ??????????????????
/*0 => out
1 => on
2 => in*/
int is_in_Polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//??????????????????2?????????
enum { out, on, in };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// ??????
//???????????????????????¨????????????????????§??¨???
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



//????????????
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon q;
	Polygon r;
	rep(i, n) {
		Point a = ps[i], b = ps[(i + 1) % n];
		Line m = Line(a, b);
		if (ccw(l.a, l.b, a) != -1) q.push_back(a);
		if (ccw(l.a, l.b, a) != 1) r.push_back(a);
		if (ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0 && isis_ll(l, m)) {
			q.push_back(is_ll(l, m));
			r.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ q,r };
	return polys;
}


int main() {
	while (1) {
		int N; cin >> N;
		if (!N)break;
		Polygon poly;
		for (int i = 0; i < N; ++i) {
			int x, y; cin >> x >> y;
			poly.push_back(Point(x, y));
		}
		vector<Point>sects(poly);
		for (int i = 0; i < N; ++i) {
			Line l1(poly[i], poly[(i + 1) % N]);
			for (int j = 0; j < N; ++j) {
				Line l2(poly[j], poly[(j + 1) % N]);
				auto ps = is_ll2(l1, l2);
				if (ps.size() == 1) {
					if (isis_sp(l1, ps[0])) {

						sects.push_back(ps[0]);
					}
				}
			}
		}
		vector<vector<int>>oks(N, vector<int>(sects.size()));
		for (int i = 0; i < N; ++i) {
			//Line l1(poly[i], poly[(i + 1) % N]);
			//Line l2(poly[i], poly[(i + N - 1) % N]);
			for (int j = 0; j < sects.size(); ++j) {
				Line l(poly[i], sects[j]);
				bool ok = true;
				vector<Point>aps;
				for (int k = 0; k < N; ++k) {
					Line edge(poly[k], poly[(k + 1) % N]);
					if (abs(cross(edge.b - edge.a, l.b - l.a))<eps) {

					}
					else if(isis_ss(l,edge)){
						Point p(is_ll(l, edge));
						aps.emplace_back(p);
						if ( l.a!=p&&l.b!=p&&edge.a!=p&&edge.b!=p) {
							ok = false;
						}
					}
				}
				sort(aps.begin(), aps.end());
				
				for (int k = 0; k < int(aps.size()) - 1; ++k) {
					if (!is_in_Polygon(poly, (aps[k] + aps[k + 1]) / (2.l))) {
						ok = false;
					}
				}
				oks[i][j] = ok;
			}
		}
		int ans = 16;
		for (int i = 0; i < (1 << N); ++i) {
			bitset<16>bs(i);
			vector<int>cats(sects.size());
			for (int j = 0; j < N; ++j) {
				if (bs[j]) {
					for (int k = 0; k < sects.size(); ++k) {
						cats[k] |= oks[j][k];
					}
				}
			}
			if (count(cats.begin(), cats.end(), 0) == 0)ans = min(ans,int( bs.count()));
		}
		cout << ans << endl;
	}
	return 0;
}
accuracy: 0.42857142857142855
time_ms: 110
memory_kb: 3236
final_rank: 13

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
const ld eps = 1e-9;

typedef ld  Weight;
struct Edge {
	int src, dest;
	int cap, rev;
	Weight weight;
	bool operator < (const Edge &rhs) const { return weight > rhs.weight; }
};


/* ??????????????¬ */

#include <complex>

typedef complex<ld> Point;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(x) (x).begin(),(x).end()


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
	bool operator==(const Point &lhs, const Point &rhs) {
		return abs(rhs - lhs) < eps;
	}
	bool operator!=(const Point &lhs, const Point &rhs) {
		return abs(rhs - lhs) > eps;
	}
}

// ????????\???
Point input_Point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// ????????????????????????
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// ??????
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// ??????
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// ??´????????????
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// ????????????
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// ccw
// 1: a,b,c??????????¨???¨?????????????????¶
//-1: a,b,c???????¨???¨?????????????????¶
// 2: c,a,b???????????´???????????¶
//-2: a,b,c???????????´???????????¶
// 0: a,c,b???????????´???????????¶
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,c??????????¨???¨?????????????????¶
	if (cross(nb, nc) < -eps) return -1; // a,b,c???????¨???¨?????????????????¶
	if (dot(nb, nc) < 0) return 2;       // c,a,b???????????´???????????¶
	if (norm(nb) < norm(nc)) return -2;  // a,b,c???????????´???????????¶
	return 0;                          // a,c,b???????????´???????????¶
}


/* ???????????? */

// ??´?????¨??´??????????????????
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// ??´?????¨?????????????????????
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// ????????¨?????????????????????
bool isis_ss(const Line& s, const Line& t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
		ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

// ????????´????????????
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// ?????????????????????
bool isis_sp(const Line& s, const Point& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// ??????????¶?
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.b - l.a) / norm(l.a - l.b);
	return l.a + t * (l.b - l.a);
}

//???????±??????????????????????
Point reflect(const Line &l, const Point &p) {
	Point pr = proj(l, p);
	return pr * 2.l - p;
}

// ??´?????¨??´????????????
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// ??´?????¨??´????????????
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// ????????¨???????????????
//???????????£????????¨???????????¨assert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//??????isis_ss?????????
		assert(false);
		return Point(0, 0);
	}
}
// ????????¨???????????????
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// ??´?????¨???????????¢
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

//??´?????¨??´???????????¢
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// ??´?????¨??????????????¢
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// ????????¨???????????¢
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// ????????¨??????????????¢
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//??´?????¨??´?????????????????????????????????
Line bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}


//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:??????
//c:????????§??????
//???????????´?????????????????¢?????????????±??????????
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* ??? */

// ?????¨????????????
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

//???????????????????????????
/*  0 => out
1 => on
2 => in*/
int is_in_Circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
//???lc??????rc??????????????????
/*0 => out
1 => on
2 => in*/
int Circle_in_Circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// ?????¨??´????????????
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// ?????¨??????????????¢
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// ?????¨????????\???
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// ?????¨????????\???
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), all(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//??????????????????????????¢???
ld two_Circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* ????§???¢ */

typedef vector<Point> Polygon;

// ??¢???
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	rep(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

//????§???¢????????¢??????
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// ??????????????????
/*0 => out
1 => on
2 => in*/
int is_in_Polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//??????????????????2?????????
enum { out, on, in };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// ??????
//???????????????????????¨????????????????????§??¨???
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



//????????????
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon q;
	Polygon r;
	rep(i, n) {
		Point a = ps[i], b = ps[(i + 1) % n];
		Line m = Line(a, b);
		if (ccw(l.a, l.b, a) != -1) q.push_back(a);
		if (ccw(l.a, l.b, a) != 1) r.push_back(a);
		if (ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0 && isis_ll(l, m)) {
			q.push_back(is_ll(l, m));
			r.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ q,r };
	return polys;
}


int main() {
	while (1) {
		int N; cin >> N;
		if (!N)break;
		Polygon poly;
		for (int i = 0; i < N; ++i) {
			int x, y; cin >> x >> y;
			poly.push_back(Point(x, y));
		}
		vector<Point>sects(poly);
		for (int i = 0; i < N; ++i) {
			Line l1(poly[i], poly[(i + 1) % N]);
			for (int j = 0; j < N; ++j) {
				Line l2(poly[j], poly[(j + 1) % N]);
				auto ps = is_ll2(l1, l2);
				if (ps.size() == 1) {
					if (isis_sp(l1, ps[0])) {

						sects.push_back(ps[0]);
					}
				}
			}
		}
		vector<vector<int>>oks(N, vector<int>(sects.size()));
		for (int i = 0; i < N; ++i) {
			//Line l1(poly[i], poly[(i + 1) % N]);
			//Line l2(poly[i], poly[(i + N - 1) % N]);
			for (int j = 0; j < sects.size(); ++j) {
				Line l(poly[i], sects[j]);
				bool ok = true;
				vector<Point>aps;
				for (int k = 0; k < N; ++k) {
					Line edge(poly[k], poly[(k + 1) % N]);
					if (abs(cross(edge.b - edge.a, l.b - l.a))<eps) {

					}
					else if(isis_ss(l,edge)){
						Point p(is_ll(l, edge));
						aps.emplace_back(p);
						if ( l.a!=p&&l.b!=p&&edge.a!=p&&edge.b!=p) {
							ok = false;
						}
					}
				}
				sort(aps.begin(), aps.end());
				for (int i = 0; i < int(aps.size()) - 1; ++i) {
					if (!is_in_Polygon(poly, (aps[i] + aps[i + 1]) / (2.l))) {
						ok = false;
					}
				}
				oks[i][j] = ok;
			}
		}
		int ans = 16;
		for (int i = 0; i < (1 << N); ++i) {
			bitset<16>bs(i);
			vector<int>cats(sects.size());
			for (int j = 0; j < N; ++j) {
				if (bs[j]) {
					for (int k = 0; k < sects.size(); ++k) {
						cats[k] |= oks[j][k];
					}
				}
			}
			if (count(cats.begin(), cats.end(), 0) == 0)ans = min(ans,int( bs.count()));
		}
		cout << ans << endl;
	}
	return 0;
}
accuracy: 0.42857142857142855
time_ms: 110
memory_kb: 3208
final_rank: 12

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
const ld eps = 1e-9;

typedef ld  Weight;
struct Edge {
	int src, dest;
	int cap, rev;
	Weight weight;
	bool operator < (const Edge &rhs) const { return weight > rhs.weight; }
};


/* ??????????????¬ */

#include <complex>

typedef complex<ld> Point;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(x) (x).begin(),(x).end()


const ld pi = acos(-1.0);
const ld dtop = pi / 180.;
const ld ptod = 1. / dtop;

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
	bool operator==(const Point &lhs, const Point &rhs) {
		return abs(rhs - lhs) < eps;
	}
	bool operator!=(const Point &lhs, const Point &rhs) {
		return abs(rhs - lhs) > eps;
	}
}

// ????????\???
Point input_Point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

// ????????????????????????
bool eq(const ld a, const ld b) {
	return (abs(a - b) < eps);
}

// ??????
ld dot(const Point& a, const Point& b) {
	return real(conj(a) * b);
}

// ??????
ld cross(const Point& a, const Point& b) {
	return imag(conj(a) * b);
}

// ??´????????????
class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
	Point operator[](const int _num)const {
		if (_num == 0)return a;
		else if (_num == 1)return b;
		else {
			assert(false);
			return Point();
		}
	}
};

// ????????????
class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

// ccw
// 1: a,b,c??????????¨???¨?????????????????¶
//-1: a,b,c???????¨???¨?????????????????¶
// 2: c,a,b???????????´???????????¶
//-2: a,b,c???????????´???????????¶
// 0: a,c,b???????????´???????????¶
int ccw(const Point& a, const Point &b, const Point &c) {
	const Point nb(b - a);
	const Point nc(c - a);
	if (cross(nb, nc) > eps) return 1;   // a,b,c??????????¨???¨?????????????????¶
	if (cross(nb, nc) < -eps) return -1; // a,b,c???????¨???¨?????????????????¶
	if (dot(nb, nc) < 0) return 2;       // c,a,b???????????´???????????¶
	if (norm(nb) < norm(nc)) return -2;  // a,b,c???????????´???????????¶
	return 0;                          // a,c,b???????????´???????????¶
}


/* ???????????? */

// ??´?????¨??´??????????????????
bool isis_ll(const Line& l, const Line& m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

// ??´?????¨?????????????????????
bool isis_ls(const Line& l, const Line& s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

// ????????¨?????????????????????
bool isis_ss(const Line& s, const Line& t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
		ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

// ????????´????????????
bool isis_lp(const Line& l, const Point& p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

// ?????????????????????
bool isis_sp(const Line& s, const Point& p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

// ??????????¶?
Point proj(const Line &l, const Point& p) {
	ld t = dot(p - l.a, l.b - l.a) / norm(l.a - l.b);
	return l.a + t * (l.b - l.a);
}

//???????±??????????????????????
Point reflect(const Line &l, const Point &p) {
	Point pr = proj(l, p);
	return pr * 2.l - p;
}

// ??´?????¨??´????????????
Point is_ll(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}
// ??´?????¨??´????????????
vector<Point> is_ll2(const Line &s, const Line& t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	if (cross(sv, tv) != 0)return vector<Point>(1, is_ll(s, t));
	else {
		vector<Point>ans;
		for (int k = 0; k < 2; ++k) {
			if (isis_sp(s, t[k]) && find(ans.begin(), ans.end(), t[k]) == ans.end())ans.push_back(t[k]);
			if (isis_sp(t, s[k]) && find(ans.begin(), ans.end(), s[k]) == ans.end())ans.push_back(s[k]);
		}
		return ans;
	}
}
// ????????¨???????????????
//???????????£????????¨???????????¨assert(false)
Point is_ss(const Line &s, const Line& t) {
	if (isis_ss(s, t)) {
		for (int k = 0; k < 2; ++k) {
			for (int l = 0; l < 2; ++l) {
				if (s[k] == t[l])return s[k];
			}
		}
		return is_ll(s, t);
	}
	else {
		//??????isis_ss?????????
		assert(false);
		return Point(0, 0);
	}
}
// ????????¨???????????????
vector<Point> is_ss2(const Line &s, const Line& t) {
	vector<Point> kouho(is_ll2(s, t));
	vector<Point>ans;
	for (auto p : kouho) {
		if (isis_sp(s, p) && isis_sp(t, p))ans.emplace_back(p);
	}
	return ans;
}
// ??´?????¨???????????¢
ld dist_lp(const Line& l, const Point& p) {
	return abs(p - proj(l, p));
}

//??´?????¨??´???????????¢
ld dist_ll(const Line& l, const Line& m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

// ??´?????¨??????????????¢
ld dist_ls(const Line& l, const Line& s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

// ????????¨???????????¢
ld dist_sp(const Line& s, const Point& p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

// ????????¨??????????????¢
ld dist_ss(const Line& s, const Line& t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}


//??´?????¨??´?????????????????????????????????
Line bisection(const Line &s, const Line &t) {
	const Point laglanju(is_ll(s, t));
	const Point avec = !(abs(laglanju - s[0])<eps) ? s[0] - laglanju : s[1] - laglanju;
	const Point bvec = !(abs(laglanju - t[0])<eps) ? t[0] - laglanju : t[1] - laglanju;

	return Line(laglanju, laglanju + (abs(bvec)*avec + abs(avec)*bvec) / (abs(avec) + abs(bvec)));
}


//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
Point  inner_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i <static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (vertics[0] == vertics[1] || vertics[1] == vertics[2] || vertics[2] == vertics[0])return vertics[0];
	Line bi1(bisection(Line(vertics[0], vertics[1]), Line(vertics[0], vertics[2])));
	Line bi2(bisection(Line(vertics[1], vertics[2]), Line(vertics[1], vertics[0])));
	if (bi1[0] == bi2[0])return bi1[0];
	else {
		return is_ll(bi1, bi2);
	}
}

//???????????´?????????????????????
//???????????´??????????????§???????????¨????¢?????????¨?????????
vector<Point>  ex_center(const vector<Line>&ls) {
	vector<Point>vertics;
	for (int i = 0; i < static_cast<int>(ls.size()); ++i) {
		vertics.push_back(is_ll(ls[i], ls[(i + 1) % 3]));
	}
	if (abs(vertics[0] - vertics[1])<eps || abs(vertics[1] - vertics[2])<eps || (abs(vertics[2] - vertics[0])<eps))return vector<Point>();
	vector<Point>ecs;
	for (int i = 0; i < 3; ++i) {
		Line bi1(bisection(Line(vertics[i], vertics[i] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[i], vertics[(i + 1) % 3])));
		Line bi2(bisection(Line(vertics[(i + 1) % 3], vertics[(i + 1) % 3] * 2.0l - vertics[(i + 2) % 3]), Line(vertics[(i + 1) % 3], vertics[i])));
		ecs.push_back(is_ll(bi1, bi2));
	}
	return ecs;
}


//a,b:??????
//c:????????§??????
//???????????´?????????????????¢?????????????±??????????
vector<Point>  same_dis(const vector<Line>&ls) {
	vector<Point>vertics;
	vertics.push_back(is_ll(ls[0], ls[2]));
	vertics.push_back(is_ll(ls[1], ls[2]));

	if (abs(vertics[0] - vertics[1]) < eps)return vector<Point>{vertics[0]};
	Line bis(bisection(ls[0], ls[1]));
	vector<Point>ecs;

	Line abi(bisection(Line(vertics[0], vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, abi));


	Line bbi(bisection(Line(vertics[0], 2.l*vertics[0] - vertics[1]), ls[0]));
	ecs.push_back(is_ll(bis, bbi));

	return ecs;
}
/* ??? */

// ?????¨????????????
vector<Point> is_cc(const Circle& c1, const Circle& c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res; // no intersection
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

//???????????????????????????
/*  0 => out
1 => on
2 => in*/
int is_in_Circle(const Circle &cir, const  Point& p) {
	ld dis = abs(cir.p - p);
	if (dis > cir.r + eps)return 0;
	else if (dis < cir.r - eps)return 2;
	else return 1;
}
//???lc??????rc??????????????????
/*0 => out
1 => on
2 => in*/
int Circle_in_Circle(const Circle &lc, const  Circle&rc) {
	ld dis = abs(lc.p - rc.p);
	if (dis < rc.r - lc.r - eps)return 2;
	else if (dis>rc.r - lc.r + eps)return 0;
	else return 1;
}

// ?????¨??´????????????
vector<Point> is_lc(const Circle& c, const Line& l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety;
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

// ?????¨??????????????¢
vector<Point> is_sc(const Circle& c, const Line& l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

// ?????¨????????\???
vector<Line> tangent_cp(const Circle& c, const Point& p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

// ?????¨????????\???
vector<Line> tangent_cc(const Circle& c1, const Circle& c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), all(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}
//??????????????????????????¢???
ld two_Circle_area(const Circle&l, const Circle&r) {
	ld dis = abs(l.p - r.p);
	if (dis > l.r + r.r)return 0;
	else if (dis + r.r < l.r) {
		return r.r*r.r*pi;
	}
	else if (dis + l.r < r.r) {
		return l.r*l.r*pi;
	}
	else {
		ld ans = (l.r)*(l.r)*acos((dis*dis + l.r*l.r - r.r*r.r) / (2 * dis*l.r)) +
			(r.r)*(r.r)*acos((dis*dis + r.r*r.r - l.r*l.r) / (2 * dis*r.r)) -
			sqrt(4 * dis*dis*l.r*l.r - (dis*dis + l.r*l.r - r.r*r.r)*(dis*dis + l.r*l.r - r.r*r.r)) / 2;
		return ans;
	}

}

/* ????§???¢ */

typedef vector<Point> Polygon;

// ??¢???
ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	rep(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

//????§???¢????????¢??????
bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

// ??????????????????
/*0 => out
1 => on
2 => in*/
int is_in_Polygon(const Polygon &poly, const  Point& p) {
	ld angle = 0;
	int n = poly.size();
	rep(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}
//??????????????????2?????????
enum { out, on, in };
int convex_contains(const Polygon &P, const Point &p) {
	const int n = P.size();
	Point g = (P[0] + P[n / 3] + P[2 * n / 3]) / 3.0l; // inner-point
	int a = 0, b = n;
	while (a + 1 < b) { // invariant: c is in fan g-P[a]-P[b]
		int c = (a + b) / 2;
		if (cross(P[a] - g, P[c] - g) > 0) { // angle < 180 deg
			if (cross(P[a] - g, p - g) > 0 && cross(P[c] - g, p - g) < 0) b = c;
			else                                                  a = c;
		}
		else {
			if (cross(P[a] - g, p - g) < 0 && cross(P[c] - g, p - g) > 0) a = c;
			else                                                  b = c;
		}
	}
	b %= n;
	if (cross(P[a] - p, P[b] - p) < 0) return 0;
	if (cross(P[a] - p, P[b] - p) > 0) return 2;
	return 1;
}

// ??????
//???????????????????????¨????????????????????§??¨???
Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}



//????????????
vector<Polygon> convex_cut(const Polygon &ps, const Line& l) {
	int n = ps.size();
	Polygon q;
	Polygon r;
	rep(i, n) {
		Point a = ps[i], b = ps[(i + 1) % n];
		Line m = Line(a, b);
		if (ccw(l.a, l.b, a) != -1) q.push_back(a);
		if (ccw(l.a, l.b, a) != 1) r.push_back(a);
		if (ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0 && isis_ll(l, m)) {
			q.push_back(is_ll(l, m));
			r.push_back(is_ll(l, m));
		}
	}
	const vector<Polygon>polys{ q,r };
	return polys;
}


int main() {
	while (1) {
		int N; cin >> N;
		if (!N)break;
		Polygon poly;
		for (int i = 0; i < N; ++i) {
			int x, y; cin >> x >> y;
			poly.push_back(Point(x, y));
		}
		vector<Point>sects(poly);
		for (int i = 0; i < N; ++i) {
			Line l1(poly[i], poly[(i + 1) % N]);
			for (int j = 0; j < N; ++j) {
				Line l2(poly[j], poly[(j + 1) % N]);
				auto ps = is_ll2(l1, l2);
				if (ps.size() == 1) {
					if (isis_sp(l1, ps[0])) {

						sects.push_back(ps[0]);
					}
				}
			}
		}
		vector<vector<int>>oks(N, vector<int>(sects.size()));
		for (int i = 0; i < N; ++i) {
			//Line l1(poly[i], poly[(i + 1) % N]);
			//Line l2(poly[i], poly[(i + N - 1) % N]);
			for (int j = 0; j < sects.size(); ++j) {
				Line l(poly[i], sects[j]);
				bool ok = true;
				for (int k = 0; k < N; ++k) {
					Line edge(poly[k], poly[(k + 1) % N]);
					if (abs(cross(edge.b - edge.a, l.b - l.a))<eps) {

					}
					else {
						Point p(is_ll(l, edge));
						if (isis_ss(l,edge)&& l.a!=p&&l.b!=p&&edge.a!=p&&edge.b!=p) {
							ok = false;
						}
						for (ld n = 0.025; n < 1; n += 0.05) {
							if (!is_in_Polygon(poly, l.a*n + l.b*(1. - n)))ok = false;
						}

					}
				}
				oks[i][j] = ok;
			}
		}
		int ans = 16;
		for (int i = 0; i < (1 << N); ++i) {
			bitset<16>bs(i);
			vector<int>cats(sects.size());
			for (int j = 0; j < N; ++j) {
				if (bs[j]) {
					for (int k = 0; k < sects.size(); ++k) {
						cats[k] |= oks[j][k];
					}
				}
			}
			if (count(cats.begin(), cats.end(), 0) == 0)ans = min(ans,int( bs.count()));
		}
		cout << ans << endl;
	}
	return 0;
}
accuracy: 0.42857142857142855
time_ms: 3990
memory_kb: 3268
final_rank: 20