HDU4720(简单几何)

Naive and Silly Muggles

 

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1123    Accepted Submission(s): 749

 

 

Problem Description

Three wizards are doing a experiment. To avoid from bothering, a special magic is set around them. The magic forms a circle, which covers those three wizards, in other words, all of them are inside or on the border of the circle. And due to save the magic power, circle's area should as smaller as it could be.
Naive and silly "muggles"(who have no talents in magic) should absolutely not get into the circle, nor even on its border, or they will be in danger.
Given the position of a muggle, is he safe, or in serious danger?

 

 

Input

The first line has a number T (T <= 10) , indicating the number of test cases.
For each test case there are four lines. Three lines come each with two integers xi and yi (|xi, yi| <= 10), indicating the three wizards' positions. Then a single line with two numbers qx and qy (|qx, qy| <= 10), indicating the muggle's position.

 

 

Output

For test case X, output "Case #X: " first, then output "Danger" or "Safe".

 

 

Sample Input

 

3 0 0 2 0 1 2 1 -0.5 0 0 2 0 1 2 1 -0.6 0 0 3 0 1 1 1 -1.5

 

 

Sample Output

 

Case #1: Danger Case #2: Safe Case #3: Safe

 

题意即时让你求三点的最小覆盖圆,其中有一点就是当这三点构成的三角形是钝角三角形的时候,最小覆盖圆的圆心为最长边两点的中点,半径为最长边的一半。

可以将三点引申思考为三角形的外接圆,考虑每种情况,然后在特殊情况特殊处理。

 

我自己的做法是用高中的知识来求非特殊情况的圆心;

如果这两个点的斜率的负倒数不存在,那么可以交换这两个值;使得处理的这两个点有解。

#include <bits/stdc++.h>
using namespace std;



#define pi acos(-1)
#define endl '\n'
#define me(x) memset(x,0,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,-1,-1,1,1};
const int dy[]={0,1,0,-1,1,-1,1,-1};
const int maxn=1e3+5;
const int maxx=1e7+1;
const double EPS=1e-7;
const int mod=1000000007;
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
struct node
{
    double x, y;
};
double getk(node a, node b)
{
    if(a.x == b.x)
        return 0.0;
    return (b.x - a.x) / (b.y - a.y) * -1;
}
double dist(node a, node b)
{
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

int main()
{
    int t;
    scanf("%d", &t);
    for(int i = 1; i <= t; i++)
    {
        node a, b, c, p;
        scanf("%lf %lf", &a.x, &a.y);
        scanf("%lf %lf", &b.x, &b.y);
        scanf("%lf %lf", &c.x, &c.y);
        scanf("%lf %lf", &p.x, &p.y);
        if(a.y == b.y)
            swap(b,c);
        if(b.y == c.y)
            swap(a,b);
        double k0 = getk(a, b);
        double k1 = getk(b, c);
        node cc, p0, p1;
        p0.x = 0.5 * (a.x + b.x);
        p0.y = 0.5 * (a.y + b.y);
        p1.x = 0.5 * (b.x + c.x);
        p1.y = 0.5 * (b.y + c.y);
        cc.x = (k0 * p0.x - p0.y - k1 * p1.x + p1.y) / (k0 - k1);
        cc.y = k0 * (cc.x - p0.x) + p0.y;
        double r = (cc.x-a.x)*(cc.x-a.x) + (cc.y-a.y)*(cc.y-a.y);
        double ab = dist(a,b);
        double bc = dist(b,c);
        double ac = dist(a,c);
        double maxx = max(ab, bc, ac);
        int flag = 1;
        if(maxx == ab && ((bc*bc+ac*ac-ab*ab)/2*bc*ac < 0))
        {
            flag = 0;
            cc.x = 0.5 * (a.x + b.x);
            cc.y = 0.5 * (a.y + b.y);
            r = ab / 2 * ab / 2;
        }
        else if(maxx == bc && ((ab*ab+ac*ac-bc*bc)/2*ab*ac < 0))
        {
            flag = 0;
            cc.x = 0.5 * (b.x + c.x);
            cc.y = 0.5 * (b.y + c.y);
            r = bc * bc / 4;
        }
        else if(maxx == ac && ((ab*ab+bc*bc-ac*ac)/2*ab*bc < 0))
        {
            flag = 0;
            cc.x = 0.5 * (a.x + c.x);
            cc.y = 0.5 * (a.y + c.y);
            r = ac * ac / 4;
        }
        if((cc.x-p.x)*(cc.x-p.x) + (cc.y-p.y)*(cc.y-p.y) - r < EPS)
            printf("Case #%d: Danger\n", i);
        else
            printf("Case #%d: Safe\n", i);

    }
    return 0;
}

 

另外还有一种求非特殊情况圆的圆心的公式;

(x0,y0)为圆心坐标:

x0 = ((y3-y1)*(y2*y2-y1*y1+x2*x2-x1*x1)+(y2-y1)*(y1*y1-y3*y3+x1*x1-x3*x3))/(2*(x2-x1)*(y3-y1)-2*(x3-x1)*(y2-y1));

y0 = ((x3-x1)*(x2*x2-x1*x1+y2*y2-y1*y1)+(x2-x1)*(x1*x1-x3*x3+y1*y1-y3*y3))/(2*(y2-y1)*(x3-x1)-2 *(y3-y1)*(x2-x1));

这是求圆心坐标的公式,自己记住再写一遍也许可以理解一些。

已知三个点的坐标是:(x1,y1),(x2,y2), (x3,y3);

 

#include <bits/stdc++.h>
using namespace std;



#define pi acos(-1)
#define endl '\n'
#define me(x) memset(x,0,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,-1,-1,1,1};
const int dy[]={0,1,0,-1,1,-1,1,-1};
const int maxn=1e3+5;
const int maxx=1e7+1;
const double EPS=1e-7;
const int mod=1000000007;
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
int main()  
{  
    int t;  
    scanf("%d",&t);  
    int Case=1;  
    while(t--)  
    {  
      double x,y,x3,x1,x2,y3,y1,y2,a,b,r2;  
      scanf("%lf%lf",&x1,&y1);  
      scanf("%lf%lf",&x2,&y2);  
      scanf("%lf%lf",&x3,&y3);  
      scanf("%lf%lf",&x,&y);  
      // 用向量点积来判断
      if((x2-x1)*(x3-x1)+(y2-y1)*(y3-y1)<0)            //(x1,y1)是钝角  
            {  
                a=(x3+x2)/2.0,b=(y3+y2)/2.0;  
                r2=(a-x2)*(a-x2)+(b-y2)*(b-y2);  
            }  
            else if((x1-x2)*(x3-x2)+(y1-y2)*(y3-y2)<0)        //(x2,y2)是钝角  
            {  
                a=(x3+x1)/2.0,b=(y3+y1)/2.0;  
                r2=(a-x1)*(a-x1)+(b-y1)*(b-y1);  
            }  
            else if((x1-x3)*(x2-x3)+(y1-y3)*(y2-y3)<0)        //(x3,y3)是钝角  
            {  
                a=(x2+x1)/2.0,b=(y2+y1)/2.0;  
                r2=(a-x1)*(a-x1)+(b-y1)*(b-y1);  
            }  
            else         //三角形是锐角三角形  
            {  
                a=((y2-y1)*(y3*y3-y1*y1+x3*x3-x1*x1)-(y3-y1)*(y2*y2-y1*y1+x2*x2-x1*x1))/(2.0*((x3-x1)*(y2-y1)-(x2-x1)*(y3-y1)));  
                b=((x2-x1)*(x3*x3-x1*x1+y3*y3-y1*y1)-(x3-x1)*(x2*x2-x1*x1+y2*y2-y1*y1))/(2.0*((y3-y1)*(x2-x1)-(y2-y1)*(x3-x1)));  
                r2=(x1-a)*(x1-a)+(y1-b)*(y1-b);  
            }  
    if((x-a)*(x-a)+(y-b)*(y-b)<=r2)  
                printf("Case #%d: Danger\n",Case++);  
            else  
                printf("Case #%d: Safe\n",Case++);  
    }  
  return 0;  
}  

 

还有一种参考网上的方法求这个点的重心(是不是重心?)

具体原理我也不知道

 

#include <bits/stdc++.h>
using namespace std;



#define pi acos(-1)
#define endl '\n'
#define me(x) memset(x,0,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define FORD(i,a,b) for(int i=(a);i<=(b);i++)
#define REP(i,b) FOR(i,0,b)
#define CLR(a) memset(a,0,sizeof(a))
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,-1,-1,1,1};
const int dy[]={0,1,0,-1,1,-1,1,-1};
const int maxn=1e3+5;
const int maxx=1e7+1;
const double EPS=1e-7;
const int mod=1000000007;
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
int main(){
    int t;
    scanf("%d",&t);
    REP(ti,t)
    {
        double x1,x2,x3,y1,y2,y3;
        double lx,ly,rx,ry;
        scanf("%lf %lf",&x1,&y1);
        scanf("%lf %lf",&x2,&y2);
        scanf("%lf %lf",&x3,&y3);
        scanf("%lf %lf",&lx,&ly);
        rx=(x1+x2+x3)/3.0;
        ry=(y1+y2+y3)/3.0;
        double r=sqrt((rx-x1)*(rx-x1)+(ry-y1)*(ry-y1));
        double leng=sqrt((rx-lx)*(rx-lx)+(ry-ly)*(ry-ly));
        if(r>=leng)printf("Case #%d: Danger\n",ti+1);
        else printf("Case #%d: Safe\n",ti+1);
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值