Sicily 1059. Exocenter of a Trian

题目大意:几何法计算三角形ABC的垂心

解题思路:根据题意解题即可,但是计算过程需要三个主要的函数。

1.向量旋转ratate():把向量分解成平行于x坐标轴和y坐标轴的向量,再分别旋转,最合把旋转结果合并。

2.求中点middle():返回两点中点即可。

3.求两直线交点intersection():只需计算两条直线即可求出交点,但是需要判断直线是否有斜率,分类讨论。


// 1059. Exocenter of a Trian
// 计算三角形的垂心 

#include <iostream>
#include <cmath>
#include <stdlib.h>
#include <stdio.h>
  
using namespace std;  

#define PI 3.141592654
#define EPS 1E-6
#define INF 1E+15

struct Point{
    double x,y;
    Point(){}
    Point( double x0, double y0 ){
        x = x0;
        y = y0;    
    }  
    
    Point& operator + ( const Point& p ){
        x = p.x + x;
        y = p.y + y;
        return *this;    
    } 
    // 两点相减得到的点代表方向向量 
    Point operator - ( const Point& p ){
        return Point( x - p.x, y - p.y );    
    } 
};

struct Line{
    double k,b;
    Line(){}
    Line( const Point& p1, const Point& p2 ){
        // 是否为垂直直线,有无斜率进行判断 
        if( fabs(p1.x - p2.x) < EPS ){
            k = INF;
            b = p1.x;
        }else{
            k = ( p1.y - p2.y )/( p1.x - p2.x );
            b = p1.y - k * p1.x; 
        }           
    }   
};

Point rotate( const Point& v, double angle );            // 向量旋转 
Point middle( const Point& p1, const Point& p2 );        // 取两点中点 
Point intersection( const Line& l1, const Line& l2 );    // 求两直线交点 

int main () {
    //freopen("D:\\input.txt","r",stdin); 
    int m;
    double x,y;
    Point A,B,C;
    
    cin >> m;
    while( m-- ){
        scanf("%lf%lf",&A.x,&A.y);
        scanf("%lf%lf",&B.x,&B.y);
        scanf("%lf%lf",&C.x,&C.y);
        
        Point D,G,L,E,J,M,O;
        D = rotate( B-A, PI/2 ) + A;
        G = rotate( C-A, -PI/2 ) + A;
        L = middle( D, G );
        
        E = rotate( A-B, -PI/2 ) + B;
        J = rotate( C-B, PI/2 ) + B;
        M = middle( E, J );
        
        O = intersection( Line(L,A), Line(M,B) );
        
        // 对x,y修正,未修正会WA 
        x = fabs(O.x) < EPS ? 0 : O.x; 
        y = fabs(O.y) < EPS ? 0 : O.y; 
        
        printf( "%.4lf %.4lf\n", x, y );          
    }
 
    return 0;  
} 

// 将向量v分解为x,y轴方向向量分别进行旋转后再进行合成 
Point rotate( const Point& v, double angle ){
    Point res;
    res.x = v.x * cos(angle) - v.y * sin(angle);
    res.y = v.x * sin(angle) + v.y * cos(angle);
    return res;    
}

Point middle( const Point& p1, const Point& p2 ){
    return Point( (p1.x + p2.x)/2.0, (p1.y + p2.y)/2.0 );    
} 

Point intersection( const Line& l1, const Line& l2 ){
    Point o;
    if( l1.k == INF ){              // 直线l1为垂直直线,无斜率 
        o.x = l1.b;
        o.y = l2.k * o.x + l2.b;
    }else if( l2.k == INF ){        // 直线l2为垂直直线,无斜率 
        o.x = l2.b;
        o.y = l1.k * o.x + l1.b;
    }else{                          // 直线l1,l2均不为垂直直线,有斜率 
        o.x = ( l1.b - l2.b )/( l2.k - l1.k );
        o.y = l1.k * o.x + l1.b;
    }    
    return o;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值