Ps:尽量不要用除法,三角函数,强制类型转换等操作,否则精度损失比较大
const double PI = acos(-1.0);
const double EPS = 1e-8;
double mul(Point p1,Point p2,Point p0)
{
return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
}
double dis(Point p1,Point p2)
{
return(sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));
}
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
bool cmp(point a,point b) // 第一次排序
{
if( dd(a.y ,b.y ) )
return xy(a.x, b.x);
return xy(a.y,b.y);
}
void Graham_scan(Point p[],Point ch[],int n,int &len) { int i,j,k=0,top=2; Point tmp; //找到最下且偏左的那个点 for(i=1; i<n; i++) if ((p[i].y<p[k].y)||((p[i].y==p[k].y)&&(p[i].x<p[k].x))) k=i; //将这个点指定为PointSet[0] tmp=p[0]; p[0]=p[k]; p[k]=tmp; //按极角从小到大,距离偏短进行排序 for (i=1; i<n-1; i++) { k=i; for (j=i+1; j<n; j++) if( (mul(p[j],p[k],p[0])>0) ||((mul(p[j],p[k],p[0])==0) &&(dis(p[0],p[j])<dis(p[0],p[k]))) ) k=j;//k保存极角最小的那个点,或者相同距离原点最近 tmp=p[i]; p[i]=p[k]; p[k]=tmp; } //第三个点先入栈 ch[0]=p[0]; ch[1]=p[1]; ch[2]=p[2]; //判断与其余所有点的关系 for (i=3; i<n; i++) { //不满足向左转的关系,栈顶元素出栈 while(mul(p[i],ch[top],ch[top-1])>=0) top--; //当前点与栈内所有点满足向左关系,因此入栈. ch[++top]=p[i]; } len=top+1; }
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
/* p[]:输入的点集 ch[]:输出的凸包上的点集,按照逆时针方向排列 n:PointSet中的点的数目 len:输出的凸包上的点的个数 */
struct Point
{
double x,y;
};
//小于0,说明向量p0p1的极角大于p0p2的极角
double mul(Point p1,Point p2,Point p0)
{
return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
}
double dis(Point p1,Point p2)
{
return(sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));
}
void Graham_scan(Point p[],Point ch[],int n,int &len)
{
int i,j,k=0,top=2;
Point tmp;
//找到最下且偏左的那个点
for(i=1; i<n; i++)
if ((p[i].y<p[k].y)||((p[i].y==p[k].y)&&(p[i].x<p[k].x)))
k=i;
//将这个点指定为PointSet[0]
tmp=p[0];
p[0]=p[k];
p[k]=tmp;
//按极角从小到大,距离偏短进行排序
for (i=1; i<n-1; i++)
{
k=i;
for (j=i+1; j<n; j++)
if( (mul(p[j],p[k],p[0])>0)
||((mul(p[j],p[k],p[0])==0)
&&(dis(p[0],p[j])<dis(p[0],p[k]))) )
k=j;//k保存极角最小的那个点,或者相同距离原点最近
tmp=p[i];
p[i]=p[k];
p[k]=tmp;
}
//第三个点先入栈
ch[0]=p[0];
ch[1]=p[1];
ch[2]=p[2];
//判断与其余所有点的关系
for (i=3; i<n; i++)
{
//不满足向左转的关系,栈顶元素出栈
while(mul(p[i],ch[top],ch[top-1])>=0) top--;
//当前点与栈内所有点满足向左关系,因此入栈.
ch[++top]=p[i];
}
len=top+1;
}
const int maxN=50000;
Point p[maxN];
Point ch[maxN];
int n;
int len;
int main()
{
int t,l;
//scanf("%d",&t);
while(~scanf("%d",&n))
{
double distence=0.0;
for(int i=0; i<n; i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
if(n==0) break;
//这是一些值得特判的情况
//if(n==0) if(n==1) if(n==2)
if(n<=1)
{
printf("0.50\n");
continue;
}
if (n == 2)
{
printf("%.2lf\n",dis(p[0],p[1])*0.50+0.50);
continue;
}
Graham_scan(p,ch,n,len);
for(int i=0; i<len; i++) //凸包 各个顶点的顺序
cout<<ch[i].x<<" "<<ch[i].y<<endl;
//求凸包的周长
double perimeters=0.0;
for(int i=1;i<len;i++)
{
perimeters+=dis(ch[i],ch[i-1]);
}
perimeters+=dis(ch[0],ch[len-1]);
printf("%.0lf\n",perimeters);
//求凸包的面积
double area=0.0;
for(int i=2; i<len; i++)
{
area+=mul(ch[i-1],ch[i],ch[0]);
}
printf("%d\n",(int )area/100);
//求图包最小圆覆盖
double maxr = -1;
double a, b, c, r, s;
for (int i=0; i<len; i++) //枚举凸包上的点
{
for (int j=i+1; j<len; j++)
{
for (int k=j+1; k<len; k++)
{
a = dis(ch[i], ch[j]);
b = dis(ch[i], ch[k]);
c = dis(ch[j], ch[k]);
if (a*a+b*b<c*c || a*a+c*c<b*b || b*b+c*c<a*a)
r = max(max(a, b), c) / 2.0;//钝角时 半径为最长边的一半
else
{
s = fabs(mul(ch[i], ch[j], ch[k])) / 2.0;
r = a * b * c / (s * 4.0);//三角形外接圆公式
}
if (maxr < r) maxr = r;
}
}
}
printf ("%.2lf\n", maxr+0.50);
//if(t) printf("\n"); //这是控制两组输出数据之间有一个空格的
}
return 0;
}
bool IsIntersected(point s1,point e1,point s2,point e2)//两个线段相交
{
return(max(s1.x,e1.x)>=min(s2.x,e2.x))&&
(max(s2.x,e2.x)>=min(s1.x,e1.x))&&
(max(s1.y,e1.y)>=min(s2.y,e2.y))&&
(max(s2.y,e2.y)>=min(s1.y,e1.y))&&
(multi(s1,s2,e1)*multi(s1,e1,e2)>0)&&
(multi(s2,s1,e2)*multi(s2,e2,e1)>0);
}
point intersection(point &A,point &B,point &C,point &D)
{
/* AB与CD交点*/
point p;
double a1=A.y-B.y;
double b1=B.x-A.x;
double c1=A.x*B.y-B.x*A.y;
double a2=C.y-D.y;
double b2=D.x-C.x;
double c2=C.x*D.y-D.x*C.y;
p.x=(b1*c2-b2*c1)/(a1*b2-a2*b1);
p.y=(a2*c1-a1*c2)/(a1*b2-a2*b1);
return p;
}
double solve(Round a, Round b)
{
double d = dis(a, b);
if (d >= a.r + b.r)
return 0;
if (d <= fabs(a.r - b.r))
{
double r = a.r < b.r ? a.r : b.r;
return PI * r * r;
}
double ang1 = acos((a.r * a.r + d * d - b.r * b.r) / 2. / a.r / d);
double ang2 = acos((b.r * b.r + d * d - a.r * a.r) / 2. / b.r / d);
double ret = ang1 * a.r * a.r + ang2 * b.r * b.r - d * a.r * sin(ang1);
return ret;
}