天天写算法之Maple trees

这个题目和前一个求周长的很相似,只不过现需要求出闭包的点来,然后再挨个计算三角形外接圆半径的最大值,最后+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 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值