![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 55;
typedef struct
{
double x,y;
}Point;
Point p[MAXN];
Point p0={0,0};
bool cmp1(const Point &a,const Point &b)//y升序,y相同x升序
{
if( a.y == b.y ) return a.x < b.x;
else return a.y < b.y;
}
double xmult(Point p1,Point p2,Point p0)//叉积>0右拐
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
bool cmp2(const Point &a,const Point &b)//极角升序
{
if( xmult(a,b,p0) < 0 ) return false;
else return true;
}
int main()
{
int n = 0,i;
//freopen("2007.txt","r",stdin);
while( scanf("%lf %lf",&p[n].x,&p[n].y) != EOF )
{
n ++;
}
sort(p+1,p+n,cmp1);
sort(p+1,p+n,cmp2);
int top = -1,S[MAXN];
S[++top] = 0;
S[++top] = 1;
for( i = 2 ; i < n ; i ++ )//grahamScan扫描法
{
while( xmult(p[i],p[S[top]],p[S[top-1]]) > 0 )
top --;
S[++top] = i;
}
for( i = 0 ; i <= top ; i ++ )
printf("(%.lf,%.lf)\n",p[i].x,p[i].y);
return 0;
}