华科网赛 G题 纯高中数学题


链接:https://www.nowcoder.com/acm/contest/106/G
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

It’s universally acknowledged that there’re innumerable trees in the campus of HUST.

Coach Yin possesses a triangular garden below his office. He wants to decorate his garden with a beautiful tree. He believes that a tree planted in place will bring good luck. A tree in place means that this tree is located at the orthocenter, centroid, incenter or circumcenter of the triangle.


Orthocenter is the intersection of the three(possibly extended) altitudes. Centroid is the intersection of the three midian line. Incenter is the intersection of three inner angular bisector. Circumcenter is the intersection of three perpendicular bisector.


It's guaranteed that the given points can form a triangle.

输入描述:

There areexactly 4 lines in each test sample.

The first to the third line consists of two integers xi and yi, denoting coordinatesof three points in plate.

The last line also consists of two integers x o and y o, denotingcoordinates the tree’s position.

The absolute valueof all coordinates are no larger than 106.

输出描述:

Print “Yes” if this tree will bring good luck, or “No” if not. Note that a tree will bring good luck if and only if it coincides with any of the four center with no error.
示例1

输入

0 1
4 2
5 0
3 1

输出

Yes
示例2

输入

10 5
3 29
3 5
6 8

输出

Yes
示例3

输入

20 18
5 6
1 4
0 0

输出

No


这道题吧,当时比赛并没有多少人做,估计是看到了这几个图吓到了,实际上,这个题还是比较简单的,就是要写四个判断,然后可能细节会出错,然后调试非常不好搞,不过通过这个题,我又再次熟悉了调试的一种方法,分模块测试,偶尔用一下,感觉效果还是挺不错的。

下面补充一下知识点吧,其实这都是高中知识点:

1、垂心:三条高线的交点   那么第一个判断就很简单了,用坐标一减,得出几个向量,然后根据向量来判断是否垂直,说到向量,这个题感觉一直都在用向量,然后再补充向量的一个知识(  两个向量a(x1,y1) ,b(x2,y2),如果x1*x2+y1*y2 = 0 则a 和 b 垂直 )

2、重心:三条中线的交点    然后,关于重心,对于这个题,有个非常简单的公式, 即  x0 =  ( x1+x2+x3)/3;  y0 = (y1+y2+y3)/3;     说出来就是 重心的横坐标是三角形三个横坐标之和的三分之一,纵坐标也是。 

3、内心:三条角平分线的交点。

4、外心:三条垂直平分线的交点。


然后讲一讲算法吧, 其实概念搞懂了,剩下的就会写了

本题很重要的一点就是要学会用向量,把两个坐标转换成一个向量。

1和2的判断就很简单了吧,就是直接套,

然后3的判断最麻烦,我就死板的根据定义来判断的,由于是角平分线的交点,那么我们算出这个平分线和相邻两边的夹角,然后判断是否相等,夹角的计算我们用向量点乘的公式,如图:




最后4的判断也不难吧,就是找到两个顶点的中点,这个中点和要判断的点组成的向量是否和边垂直。


下面是代码:


#include<iostream>
#include <cstdio>
#include<cmath>
#include<cstdlib>
using namespace std;
typedef long long ll;
typedef long double lb;
#define eps 1e-7
struct spe
{
    lb x,y;
};
spe p[5];
spe AB,BC,CA,AC,CB,BA,AD,CD,BD;     //表示相应的向量

bool verti( spe a,spe b,spe line)   //前两个变量是点,后一个是向量
{                                     //用来判断是否垂直
    lb x = a.x-b.x;
    lb y = a.y-b.y;
    if( fabs( x*line.x +y*line.y )-0 < eps )
        return true;
    return false;
}
bool judge1()
{
    if( verti(p[1],p[4],BC) == false )
        return false;
    if( verti(p[2],p[4],CA) == false )
        return false;
    if( verti(p[3],p[4],AB) == false )
        return false;
    return true;
}
bool judge2()
{
    lb x = (p[1].x+p[2].x+p[3].x)/3;
    lb y = (p[1].y+p[2].y+p[3].y)/3;
    if( fabs(x-p[4].x)<eps && fabs(y-p[4].y)<eps )
        return true;
    return false;
}
bool angle(spe a,spe m,spe b)   //判断夹角是否相等  用于judge3
{
    lb l = ( (a.x*m.x+a.y*m.y)/(sqrt( a.x*a.x+a.y*a.y )*sqrt(m.x*m.x+m.y*m.y) ) );
    lb r = ( ( b.x*m.x+b.y*m.y)/(sqrt( b.x*b.x+b.y*b.y )*sqrt(m.x*m.x+m.y*m.y) ) );
    if( fabs(l-r)<eps )
        return true;
    return false;
}
bool judge3()
{
    if( angle(AC,AD,AB) == false )
        return false;
    if( angle(BA,BD,BC) == false )
        return false;
    if( angle(CB,CD,CA) == false )
        return false;
    return true;
}
bool judge4()
{
    spe mid;
    mid.x = (p[1].x+p[3].x)/2;  mid.y = (p[1].y+p[3].y)/2;
    if( verti(mid,p[4],AC) == false )
        return false;

    mid.x = (p[2].x+p[1].x)/2;  mid.y = (p[2].y+p[1].y)/2;
    if( verti(mid,p[4],AB) == false )
        return false;

    mid.x = (p[3].x+p[2].x)/2;  mid.y = (p[3].y+p[2].y)/2;
    if( verti(mid,p[4],BC) == false )
        return false;
    return true;
}
int main()
{
    
	for( int i = 1 ; i <= 4 ; i++ )   // 4是中心点
        cin>>p[i].x>>p[i].y;

    AB.x = p[2].x-p[1].x;
    AB.y = p[2].y-p[1].y;
    BA.x = -AB.x;   BA.y = -AB.y;

    BC.x = p[3].x-p[2].x;
    BC.y = p[3].y-p[2].y;
    CB.x = -BC.x;   CB.y = -BC.y;

    CA.x = p[1].x-p[3].x;
    CA.y = p[1].y-p[3].y;
    AC.x = -CA.x;   AC.y = -CA.y;

    AD.x = p[4].x-p[1].x;   AD.y = p[4].y-p[1].y;
    BD.x = p[4].x-p[2].x;   BD.y = p[4].y-p[2].y;
    CD.x = p[4].x-p[3].x;   CD.y = p[4].y-p[3].y;

    if( judge1() )
    {
        cout<<"Yes"<<endl;
        return 0;
    }
    if( judge2() )
    {
        cout<<"Yes"<<endl;
        return 0;
    }
    if( judge3() )
    {
        cout<<"Yes"<<endl;
        return 0;
    }
    if( judge4() )
    {
        cout<<"Yes"<<endl;
        return 0;
    }
    cout<<"No"<<endl;
	return 0;
}





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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值