hdu 4720 Naive and Silly Muggles

题目大意:给出三个点,确定一个包含三个点的最小圆,然后判断点p是否在圆内(包括边上)还是圆外,

                 前者输出Danger,后者输出Safe。


解题思路:  1)如果三点共线,则最小圆的圆心即为最长边的中点

                    2)如果三点构成的三角形是锐角三角形,则最小圆的圆心即为三角形的外心

                    3)如果三点构成的三角形是钝角三角形或直角三角形,则最小圆的圆心为三角形最长边的中点


代码如下:

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;

#define eps 1e-6
struct point
{
    double x,y;
}p[4], re;
double ma = 0;
struct line
{
    point a,b;
};

double dis(point p1, point p2)
{
     return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

double  mult(point p1,point p2,point p0)
{
      return ((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
}

point intersection(line u, line v)
{
     point ret = u.a;
     double t = ((u.a.x - v.a.x) * (v.a.y - v.b.y) - (u.a.y - v.a.y) * (v.a.x - v.b.x))
                 / ((u.a.x - u.b.x) * (v.a.y - v.b.y) - (u.a.y - u.b.y) * (v.a.x - v.b.x));
     ret.x += (u.b.x-u.a.x) * t;
     ret.y += (u.b.y-u.a.y) * t;
     return ret;
}

point circumcenter(point a, point b, point c)
{
     line u, v;
     u.a.x = (a.x + b.x)/2;
     u.a.y = (a.y + b.y)/2;
     u.b.x = u.a.x - a.y + b.y;
     u.b.y = u.a.y + a.x - b.x;
     v.a.x = (a.x + c.x)/2;
     v.a.y = (a.y + c.y)/2;
     v.b.x = v.a.x - a.y + c.y;
     v.b.y = v.a.y + a.x - c.x;
     return intersection(u, v);
}

void init()
{
        double r1 = dis(p[0], p[1]);
        double r2 = dis(p[1], p[2]);
        double r3 = dis(p[0], p[2]);

        if(ma < r1)
        {
              ma = r1/2;
              re.x = (p[0].x + p[1].x)/2;
              re.y = (p[0].y + p[1].y)/2;
        }
        if(ma < r2)
        {
              ma = r2/2;
              re.x = (p[1].x + p[2].x)/2;
              re.y = (p[2].y + p[1].y)/2;
        }
        if(ma < r3)
        {
              ma = r3/2;
              re.x = (p[0].x + p[2].x)/2;
              re.y = (p[0].y + p[2].y)/2;
        }
}

bool judge(double r1, double r2, double r3)
{
      double rest = r1 * r1 + r2 * r2 -  r3 * r3;
      if(rest <= 0) return true;
      return false;
}

int main()
{
    int t;
    scanf("%d", &t);
    for(int i  = 1; i <= t; i ++)
    {
            for(int j = 0; j < 4; j ++)
            {
                    scanf("%lf %lf", &p[j].x, &p[j].y);
            }
            if(mult(p[0], p[1], p[2]) == 0)
            {
                   init();
            }
            else
            {
                  double r1 = dis(p[0], p[1]);
                  double r2 = dis(p[1], p[2]);
                  double r3 = dis(p[0], p[2]);
                  if(judge(r1, r2, r3) || judge(r1, r3, r2) || judge(r3, r2, r1))
                        init();
                  else
                  {
                        re = circumcenter(p[0], p[1], p[2]);
                        ma = dis(re, p[0]);
                  }
            }
            if(dis(re, p[3]) > ma)
            {
                  printf("Case #%d: Safe\n", i);
            }
            else
            {
                  printf("Case #%d: Danger\n", i);
            }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值