这个题目和前一个求周长的很相似,只不过现需要求出闭包的点来,然后再挨个计算三角形外接圆半径的最大值,最后+0.5得到结果。但是要钝角三角形的时候需要按其最长边计算,至于为什么我也不太清楚,可能就是求凸包最小yuan覆盖,就是这样的计算过程,如果哪位大神知道具体原理,可以告知一下。
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define MAX 50005
using namespace std;
struct point{
double x ;
double y ;
}points[MAX];
int ans[MAX];//用于记录凸包的顺时针索引
int n ;
bool cmp(point a , point b )
{
if(a.y==b.y)
return a.x<b.x;
return a.y<b.y;
}
double getDis(point a , point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double judge(point a, point b , point base )
{
return (a.x - base.x)*(b.y-base.y)-(b.x-base.x)*(a.y-base.y);
}
int bk(int n)
{
sort(points+1,points+n+1,cmp);
int index=1;
ans[1]=1 ;
do{
index++;
int t = ans[index-1]+1;//找到上一次解决的点,+1得到下一个点
if(t>n)
t = 1 ;//注意这个地方,其实把最后的点也算了进去,也就是围城了一个圈,当把最后一个点算进去的时候才中止
for(int i = 1 ; i<= n ; i ++)
{
if(judge(points[i],points[t],points[ans[index-1]])<0)
{
t = i ;
}
}//这个地方还很巧妙的把共线的情况也算了进去,很厉害,如果共线,那么上面的if肯定进不去,就会在上一个的基础上把t原封不懂得传递过来
ans[index]=t;
}while(ans[index]!=ans[1]);
return index-1 ;
}
int judgeTra(double a , double b, double c)
{
return a*a+b*b<c*c;
}
double getR(point a , point b , point c)
{
double lc = getDis(a,b);
double la = getDis(b,c);
double lb = getDis(a,c);
if(judgeTra(la,lb,lc)||judgeTra(la,lc,lb)||judgeTra(lb,lc,la))
{
return max(la/2,max(lb,lc)/2);
}else {
return la*lb*lc/(2*abs(judge(a,b,c)));
}
}
int main(){
int i , j ,k,num;
while(scanf("%d",&n),n)
{
for(i = 1 ; i <= n ; i++)
{
scanf("%lf%lf",&points[i].x,&points[i].y);
}
if(n==1)
{
printf("0.50\n");
continue ;
}else if(n==2)
{
printf("%.2lf\n",getDis(points[1],points[2])/2+0.5);
continue ;
}
num = bk(n);
double res = 0;
for(i = 1; i <=num ; i++)
{
for(j = i+1 ; j <= num ; j++)
{
for(k = j+1 ; k<=num ; k ++)
{
res = max(res,getR(points[ans[i]],points[ans[j]],points[ans[k]]));
}
}
}
printf("%.2lf\n",0.5+res);
}
return 0 ;
}