#include <iostream>
#include <math.h>
#include <algorithm>
using namespace std ;
struct Point
{
int x ;
int y ;
int flag ; //flag标记该点是否在P0与其他点连线的内部,flag=0表示在内部
}list[500];
int stack[500], top ;
void swap(Point &a, Point &b)
{
Point t ;
t = a ;
a = b ;
b = t ;
}
int CrossProd(Point p0, Point p1, Point p2)
{
return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y) ;
}
int compare(const void *pp1, const void *pp2)
{
Point *p1 = (Point*)pp1 ;
Point *p2 = (Point*)pp2 ;
return CrossProd(list[0], *p1, *p2)*(-1) ;
}
void select(int n, int &num)
{
Point p1, p2 ;
int t, i, j, count ;
for(i = 1; i < n; ++i)
{
p1 = list[i] ;
if(p1.flag)
{
for(j = i+1; j < n; ++j)
{
p2 = list[j] ;
if(p2.flag)
{
t = CrossProd(list[0], p1, p2) ; //判断两个点p1, p2是否在同一条直线上
if(t == 0)
{
if((p1.x-list[0].x)*(p1.x-list[0].x) + (p1.y-list[0].y)*(p1.y-list[0].y) <
(p2.x-list[0].x)*(p2.x-list[0].x) + (p2.y-list[0].y)*(p2.y-list[0].y))
{
list[i].flag = 0 ;
}
else list[j].flag = 0 ;
}
}
}
}
}
count = 1 ;
for(i = 1; i < n; ++i)
{
if(list[i].flag == 1)
list[count++] = list[i] ;
} //剔除掉所有flag为0的点
num = count-1 ;
qsort(list+1, num, sizeof(Point), compare) ; //对剩下的点按照对点list[0]的极角从小到大进行快速排序
}
int init(int n)
{
int i, num ;
for(i = 0; i < n; ++i)
{
cin>>list[i].x>>list[i].y ;
list[i].flag = 1 ;
if((list[i].y < list[0].y) || (list[i].y == list[0].y) && (list[i].x < list[0].x)) //边输入边寻找最低最做端的点
swap(list[0], list[i]) ;
}
select(n, num) ; //剔除掉所有初步判定为在凸包内部的点,并返回剩余点得数量
return num+1 ;
}
void graham(int n)
{
int i ;
if(n == 1)
cout<<"("<<list[0].x<<","<<list[0].y<<")"<<endl ;
if(n == 2)
cout<<"("<<list[0].x<<","<<list[0].y<<")"<<"("<<list[1].x<<","<<list[1].y<<")"<<endl ;
if(n>2)
{
for(i = 0; i <= 2; ++i)
stack[i] = i ;
top = 2 ;
for(i = 3; i <= n-1; ++i)
{
while(CrossProd(list[stack[top-1]], list[stack[top]], list[i]) <= 0) top-- ;
top++ ;
stack[top] = i ; //stack[]数组中存储的时list[]数组的下标,利用stack[]数组模拟栈
}
for(i = 0; i <= top; ++i)
cout<<"("<<list[stack[i]].x<<","<<list[stack[i]].y<<")" ;
cout<<endl ;
}
}
int main()
{
int n, num, count = 0 ;
while(cin>>n, n)
{
count++ ;
num = init(n) ;
cout<<"set "<<count<<":\n" ;
graham(num) ;
}
return 0 ;
}
/*
input:
6
1 1
2 2
1 3
2 3
3 1
3 3
0
output:
set 1:
(1,1)(3,1)(3,3)(1,3)
*/
#include <math.h>
#include <algorithm>
using namespace std ;
struct Point
{
int x ;
int y ;
int flag ; //flag标记该点是否在P0与其他点连线的内部,flag=0表示在内部
}list[500];
int stack[500], top ;
void swap(Point &a, Point &b)
{
Point t ;
t = a ;
a = b ;
b = t ;
}
int CrossProd(Point p0, Point p1, Point p2)
{
return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y) ;
}
int compare(const void *pp1, const void *pp2)
{
Point *p1 = (Point*)pp1 ;
Point *p2 = (Point*)pp2 ;
return CrossProd(list[0], *p1, *p2)*(-1) ;
}
void select(int n, int &num)
{
Point p1, p2 ;
int t, i, j, count ;
for(i = 1; i < n; ++i)
{
p1 = list[i] ;
if(p1.flag)
{
for(j = i+1; j < n; ++j)
{
p2 = list[j] ;
if(p2.flag)
{
t = CrossProd(list[0], p1, p2) ; //判断两个点p1, p2是否在同一条直线上
if(t == 0)
{
if((p1.x-list[0].x)*(p1.x-list[0].x) + (p1.y-list[0].y)*(p1.y-list[0].y) <
(p2.x-list[0].x)*(p2.x-list[0].x) + (p2.y-list[0].y)*(p2.y-list[0].y))
{
list[i].flag = 0 ;
}
else list[j].flag = 0 ;
}
}
}
}
}
count = 1 ;
for(i = 1; i < n; ++i)
{
if(list[i].flag == 1)
list[count++] = list[i] ;
} //剔除掉所有flag为0的点
num = count-1 ;
qsort(list+1, num, sizeof(Point), compare) ; //对剩下的点按照对点list[0]的极角从小到大进行快速排序
}
int init(int n)
{
int i, num ;
for(i = 0; i < n; ++i)
{
cin>>list[i].x>>list[i].y ;
list[i].flag = 1 ;
if((list[i].y < list[0].y) || (list[i].y == list[0].y) && (list[i].x < list[0].x)) //边输入边寻找最低最做端的点
swap(list[0], list[i]) ;
}
select(n, num) ; //剔除掉所有初步判定为在凸包内部的点,并返回剩余点得数量
return num+1 ;
}
void graham(int n)
{
int i ;
if(n == 1)
cout<<"("<<list[0].x<<","<<list[0].y<<")"<<endl ;
if(n == 2)
cout<<"("<<list[0].x<<","<<list[0].y<<")"<<"("<<list[1].x<<","<<list[1].y<<")"<<endl ;
if(n>2)
{
for(i = 0; i <= 2; ++i)
stack[i] = i ;
top = 2 ;
for(i = 3; i <= n-1; ++i)
{
while(CrossProd(list[stack[top-1]], list[stack[top]], list[i]) <= 0) top-- ;
top++ ;
stack[top] = i ; //stack[]数组中存储的时list[]数组的下标,利用stack[]数组模拟栈
}
for(i = 0; i <= top; ++i)
cout<<"("<<list[stack[i]].x<<","<<list[stack[i]].y<<")" ;
cout<<endl ;
}
}
int main()
{
int n, num, count = 0 ;
while(cin>>n, n)
{
count++ ;
num = init(n) ;
cout<<"set "<<count<<":\n" ;
graham(num) ;
}
return 0 ;
}
/*
input:
6
1 1
2 2
1 3
2 3
3 1
3 3
0
output:
set 1:
(1,1)(3,1)(3,3)(1,3)
*/