#include<stdio.h> #include<stdlib.h> #include<math.h> #define max 3300 struct node { int x,y; }g[max],stack[max],min; int n; void swap(int a,int b) { min=g[a];g[a]=g[b];g[b]=min; } double ans(node yuan,node zhong,node last) { return (yuan.x-zhong.x)*(last.y-zhong.y)-(last.x-zhong.x)*(yuan.y-zhong.y); } double dis(node a,node b) { return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); } int cmp(const void *a,const void *b)//逆时针排序 返回正数要交换 { node *a1=(node*)a; node *b1=(node*)b; if((ans(g[0],*a1,*b1)>0)||(ans(g[0],*a1,*b1)==0&&dis(g[0],*a1)<=dis(g[0],*b1))) return 1; else return -1; } void Graham() { int i,k; min=g[0];k=0; for(i=1;i<n;i++) if(g[i].y<min.y||(g[i].y==min.y&&g[i].x<min.x)) { min=g[i]; k=i; } swap(0,k); qsort(g+1,n-1,sizeof(g[0]),cmp); stack[0]=g[0]; stack[1]=g[1]; stack[2]=g[2]; int top=2; g[n]=g[0]; for(i=3;i<=n;i++) { while(ans(stack[top-1],stack[top],g[i])>=0)//多去掉一些点 top--; stack[++top]=g[i]; } for(i=0;i<top-1;i++) printf("(%d,%d) ",stack[i].x,stack[i].y); printf("(%d,%d)/n",stack[top-1].x,stack[top-1].y); } main() { int i,t; scanf("%d",&t); while(t--) { scanf("%d",&n); if(n==0) break; for(i=0;i<n;i++) scanf("%d%d",&g[i].x,&g[i].y); if(n==1) printf("(%d,%d)/n",g[0].x,g[0].y); else if(n==2) { if(g[1].y<g[0].y||(g[1].y==g[i].y&&g[1].x<g[0].x)) printf("(%d,%d) (%d,%d)/n",g[1].x,g[1].y,g[0].x,g[0].y); else printf("(%d,%d) (%d,%d)/n",g[0].x,g[0].y,g[1].x,g[1].y); } else Graham(); } }