//这个模板好像有点问题,有的题过不了( >﹏<。)~大家慎用
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
#define eps 1e-8
#define PI acos(0.0)*2.0
const int maxn=200005;
struct point{
double x,y;
}p[maxn],res[maxn];
double dis(point a,point b)
{
return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));
}
bool xmult(point p1,point p2,point p0)//cross product(p1-p0)X(p2-p0)
{
if(((p1.x-p0.x)*(p2.y-p0.y) >= (p2.x-p0.x)*(p1.y-p0.y)))
return false;
return true;
}
bool operator < (const point &l,const point &r)
{
return l.y<r.y || (l.y==r.y && l.x<r.x);
}
int graham(point pnt[],int n)//求凸包及凸包内点的数目
{
int i,len,top=1;
sort(pnt,pnt+n);
if(n==0) return 0;res[0] = pnt[0];
if(n==1) return 1;res[1] = pnt[1];
if(n==2) return 2;res[2] = pnt[2];
for (i = 2; i < n; i++) {
while(top &&xmult(pnt[i],res[top],res[top-1]))
top--;
res[++top] = pnt[i];
}
len = top;
res[++top] = pnt[n-2];
for (int i = n-3; i >= 0 ; i--)
{
while(top!=len &&xmult(pnt[i],res[top],res[top-1]))
top--;
res[++top] = pnt[i];
}
return top;
}
double cir_polygon(int n,point *p)//circumference
{
double cir = 0;
int i;
for (i = 0; i < n; i++)
cir += dis(p[i],p[(i+1)%n]);
return cir;
}
double area_polygon(int n,point *p)//area
{
double s1=0,s2=0;
int i;
for (i = 0; i < n; i++)
{
s1+=p[(i+1)%n].y*p[i].x;
s2+=p[(i+1)%n].y*p[(i+2)%n].x;
}
return fabs(s1-s2)/2;
}
int main()
{
int n,top;
double r;
while(cin>>n){
double ans = 0;
for (int i = 0; i < n; i++)
cin>>p[i].x>>p[i].y;
top = graham(p,n);
ans += cir_polygon(top,res);
cout<<setiosflags(ios::fixed)<<setprecision(2)<<ans<<endl;
}
return 0;
}
又来一个模板,二者选用
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;
#define MAX 100002
#define eps 1e-9
int n,cnt;
struct Point
{
double x,y;
Point (){}
Point ( double x, double y ) : x(x) , y(y) {}
}p[MAX],ch[MAX];
typedef Point Vector;
Point operator - ( Point a , Point b ) { return Point ( a.x - b.x , a.y - b.y ); }
bool cmp ( Point a , Point b ) //将每个点通过优先x最小然后y最小的顺序来排序
{
if ( a.x != b.x ) return a.x < b.x;
else return a.y < b.y;
}
int dcmp ( double x )
{
if ( fabs ( x ) < eps ) return 0;
else return x < 0 ? -1 : 1;
}
double Cross ( Vector u , Vector v ) //叉乘
{
return u.x * v.y - u.y * v.x;
}
int ConvexHull ( Point *p , Point *ch ) //求凸包Andrew算法
{
sort ( p , p + n , cmp );
int m = 0;
for ( int i = 0 ; i < n ; i ++ )
{
while ( m > 1 && dcmp ( Cross ( ch[m-1] - ch[m-2] , p[i] - ch[m-2] ) ) <= 0 ) m--;
ch[m++] = p[i];
}
int k = m;
for ( int i = n - 2 ; i >= 0 ; i -- )
{
while ( m > k && dcmp ( Cross ( ch[m-1] - ch[m-2] , p[i] - ch[m-2] ) ) <= 0 ) m --;
ch[m++] = p[i];
}
return m;
}
double dis(Point a,Point b)
{
return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));
}
double cir_polygon(Point *p)//circumference
{
double cir = 0;
int i;
for (i = 0; i < cnt; i++)
cir += dis(p[i],p[(i+1)%cnt]);
return cir;
}
double PolygonArea ( Point *ch ) //求多边形面积(因为是凸包所以它的有向面积就是它本身的面积
{
double area = 0;
for ( int i = 1 ; i < cnt -1 ; i ++ )
{
area += Cross ( ch[i] - ch[0] , ch[i+1] - ch[0] );
//cout << area << endl;
}
return area / 2.0;
}
int main()
{
int t;
scanf("%d",&t);
while ( t-- ){
scanf ( "%d" , &n );
for( int i = 0 ; i < n ; i ++ )
scanf ( "%lf%lf" , &p[i].x , &p[i].y );
cnt = ConvexHull ( p , ch );
printf ( "%.1lf\n" , PolygonArea( ch ) );
}
return 0;
}