hdu 4720 Naive and Silly Muggles (计算几何)

原题友情链接~点击此处打开链接~

这个题自认为写的代码比较挫。 = = 。没办法,比赛嘛,能A就行。

说下题意:告诉你三个点的坐标,由这三个画成的三角形构成一个面积最小的圆。然后再判断另外一个点跟这个圆的关系。

证明得:当三角形为锐角三角形或直角三角形的时候,三角形的外接圆是面积最小的圆。

当三角形为钝角三角形时,圆心钝角所对的边的中点时圆的面积最小。圆的半径是长边的一半。

然后思路就这些了。具体实现看代码吧。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;

typedef struct
{
    double x,y;
}Point;

typedef struct
{
    Point p[3];
}Traingle;

typedef struct
{
    Point center;
    double r;
}Circle;

double Dis(Point p,Point q)
{
    double dx=p.x-q.x;
    double dy=p.y-q.y;
    return sqrt(dx*dx+dy*dy);
}

double Area(Traingle ct)/*求三角形面积*/
{
    return fabs((ct.p[1].x-ct.p[0].x)*(ct.p[2].y-ct.p[0].y)-(ct.p[2].x-ct.p[0].x)*(ct.p[1].y-ct.p[0].y))/2.0;
}

Circle CircumCircle(Traingle t)/*求外接圆*/
{
    Circle tmp;
    double a, b, c, c1, c2;
    double xA, yA, xB, yB, xC, yC;
    a = Dis(t.p[0], t.p[1]);
    b = Dis(t.p[1], t.p[2]);
    c = Dis(t.p[2], t.p[0]);
    tmp.r = (a*b*c)/(Area(t)*4.0);
    xA = t.p[0].x;
    yA = t.p[0].y;
    xB = t.p[1].x;
    yB = t.p[1].y;
    xC = t.p[2].x;
    yC = t.p[2].y;
    c1 = (xA*xA+yA*yA - xB*xB-yB*yB) / 2;
    c2 = (xA*xA+yA*yA - xC*xC-yC*yC) / 2;
    tmp.center.x = (c1*(yA - yC)-c2*(yA - yB)) / ((xA - xB)*(yA - yC)-(xA - xC)*(yA - yB));
    tmp.center.y = (c1*(xA - xC)-c2*(xA - xB)) / ((yA - yB)*(xA - xC)-(yA - yC)*(xA - xB));
    return tmp;
}

double cos(double a,double b,double c)
{
    return (pow(a,2) + pow(b,2) - pow(c,2))/2*a*b;
}

int main()
{
    int ncase;
    Point point[10];
    double Line[10];
    double Cos[10];
    scanf("%d",&ncase);
    int K = 0;
    while(ncase--)
    {
        Traingle ct;
        Circle ans;
        bool flag = false;
        for(int i = 0 ; i < 4 ; i++)
        {
            scanf("%lf %lf",&point[i].x,&point[i].y);
            ct.p[i] = point[i];
        }
        Line[0] = Dis(point[0],point[1]);
        Line[1] = Dis(point[1],point[2]);
        Line[2] = Dis(point[2],point[0]);
        Cos[0] = cos(Line[0],Line[1],Line[2]);
        Cos[1] = cos(Line[0],Line[2],Line[1]);
        Cos[2] = cos(Line[1],Line[2],Line[0]);
        printf("Case #%d: ",++K);
        for(int i = 0 ; i < 3 ; i++)
        {
            if(Cos[i] < 0)
            {
                flag = true;
                break;
            }
        }
        if(flag == true)
        {

            double mx = 0.0;
            int a,x1,x2;
            for(int i = 0 ; i < 3 ; i++)
            {
                if(mx < Line[i])
                {
                    mx = Line[i];
                    a = i;
                }
            }
            if(a == 0)
            {
                x1 = 0;
                x2 = 1;
            }
            else if(a == 1)
            {
                x1 = 1;
                x2 = 2;
            }
            else
            {
                x1 = 2;
                x2 = 0;
            }
            double R = mx/2;
            Point centerx;
            centerx.x = (point[x1].x + point[x2].x)/2;
            centerx.y = (point[x1].y + point[x2].y)/2;
            if(Dis(centerx,point[3]) > R)
            {
                printf("Safe\n");
            }
            else
            {
                printf("Danger\n");
            }
        }
        else
        {
            ans = CircumCircle(ct);
            double k = Dis(ans.center,point[3]);
            if(k > ans.r)
            {
                printf("Safe\n");
            }
            else
            {
                printf("Danger\n");
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值