求凸包的水题,这题输入很有特点。注意: 要求凸包第一个点是最下方的点。
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
using namespace std;
const int MAX = 120000;
const double eps = 1e-6;
const double pi=3.141592654;
bool dy(double x,double y) { return x > y + eps;} // x > y
bool xy(double x,double y) { return x < y - eps;} // x < y
bool dyd(double x,double y) { return x > y - eps;} // x >= y
bool xyd(double x,double y) { return x < y + eps;} // x <= y
bool dd(double x,double y) { return fabs( x - y ) < eps;} // x == y
struct point{ double x,y; };
point c[MAX];
double disp2p(point a,point b)
{
return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
}
double crossProduct(point a,point b,point c)//向量 ac 在 ab 的方向
{
return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);
}
bool cmp(point a,point b) // 排序
{
double len = crossProduct(c[0],a,b);
if( dd(len,0.0) )
return xy(disp2p(c[0],a),disp2p(c[0],b));
return xy(len,0.0);
}
int stk[MAX];
int top;
double sum = 0.0;
void Graham(int n)
{
int tmp = 0;
for(int i=1; i<n; i++)//
if( xy(c[i].y,c[tmp].y) || dd(c[i].y,c[tmp].y) && xy(c[i].x,c[tmp].x) )
tmp = i;
swap(c[0],c[tmp]);
sort(c+1,c+n,cmp);
stk[0] = 0; stk[1] = 1;
top = 1;
for(int i=2; i<n; i++)
{
while( xyd( crossProduct(c[stk[top]],c[stk[top-1]],c[i]), 0.0 ) && top >= 1 )
top--;
stk[++top] = i;
}
//cout<<"top "<<top<<endl;
}
int main()
{
int n,t;
int flag=1;
while(cin>>t && t )
{
while(t--)
{
cin>>n;
for(int i=0;i<n;i++)
cin>>c[i].x>>c[i].y;
Graham(n);
if(flag)
{
cout<<t+1<<endl;
flag=0;
}
cout<<top+2<<endl;
for(int i=0; i<=top; i++)
printf("%.0lf %.0lf\n",c[stk[i]].x,c[stk[i]].y);
printf("%.0lf %.0lf\n",c[stk[0]].x,c[stk[0]].y);
if(t!=0)
{
cin>>n;
cout<<n<<endl;
}
}
}
return 0;
}