zoukankan      html  css  js  c++  java
  • 通过三条直线求出围成三角形的面积

    背景

    众所周知,三角形是三条相交的直线围成的图形,就像这样:

    这篇博客的灵感和上一篇一样,同样是来自于初二一次函数的常考题型:一直一条直线,求出它与x轴和y轴围成三角形的面积。

    这个问题是很好解决的,只需要将 x=0 和 y=0 代入直线的解析式,算出与坐标轴的交点坐标A和B。因为两条坐标轴相互垂直,两个交点离原点的距离就是两条直角边的长,再根据三角形面积公式,就可以求出三角形的面积。 

    直到,我又看到了另一道题,要通过两条直线求它们与坐标轴围成的三角形的面积。

    解决这个问题,要求出两条直线的交点。可以通过方程求出,然后再求出它们与坐标轴的交点,这样一来,我们就成功得到了底和高。

    于是,我干脆继续拓展,通过三条直线确定围成三角形的面积,就有了这个我搞了大半个月的项目和一直咕咕的博客。

    大致思路

    • 为保证精度,程序中所有关于点、线、面积的操作全部使用分数。不过C艹并不支持分数,于是我就手写了一个(突然感觉python的魔法方法(相当于C中的运算符重载)真香~)
    • 先求出三条直线形成的三个交点
    • 求出包含这个三角形的,四条边与坐标轴平行的,且面积最小的长方形的面积,然后减去三个比要求的三角形多出来的小三角形的面积。说的这么复杂,实际上就是初中生都学过的割补法。。
    • 长方形的四条边,分别是最靠上,靠下的点所在的与x轴平行的直线,和最靠左,靠右的点与y轴平行的直线。

    后两条更直观一点,就是这样:

    推导过程

    先求交点

    设两条直线的斜率和截距分别为:k1,b1, k2, b2

    可得方程:k1*x+b1=k2*x+b2

    通过简单的移项可得:

    再通过将x带入到其中一个函数中求得y

     以此类推,求出三个交点的坐标。

    求长方形面积

    (横坐标值最大的点的横坐标值-横坐标值最小的点的横坐标值)*(纵坐标值最大的点的纵坐标值-纵坐标值最小的点的纵坐标值)

    说白了就是找出最靠上的点和最靠下的点,最靠左的点与最靠右的点,然后算出长方形的长和宽。

    求小三角形的面积

    对于每两个交点,都可一确定一个以这条边为斜边的直角三角形的面积。

    两个点的横坐标的差的绝对值和纵坐标的差的绝对值,就是这个三角形的两条直角边的长度,再根据公式求出面积。

    求大三角形的面积

    长方形面积 - 三个小三角形面积之和

    局限性&解决办法

    这种方法非常的简单易懂,但是对于钝角三角形并不适用,就比如这个:

    解决这个问题也比较简单:当你知道两个点的坐标时,就可以利用勾股定理算出它们的距离,也就是三角形的边长,再套用海伦公式,就可以算出来面积

    但是我还没有搞懂海伦公式,再说哪个出题的会出这么难且geliao的题啊。。

     等我证出来了海伦公式在搞这个吧。。

    代码

    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    struct fenshu{
        int fz, fm;
    };
    struct fenshu k[4], b[4], x12, y12, x23, y23, x13, y13, xmax, ymax, xmin, ymin;
    int tp;
    
    int gcd(int a, int b){
        if(b==0) return a;
        return gcd(b, a%b);
    }
    fenshu build(int a, int b){
        fenshu fs;
        int gc=gcd(a, b);
        fs.fz=a/gc; fs.fm=b/gc;
        if(fs.fm<0){
            fs.fz=-fs.fz;
            fs.fm=-fs.fm;
        }
        return fs;
    }
    fenshu add(fenshu a, fenshu b){
        return build(a.fz*b.fm+b.fz*a.fm, a.fm*b.fm);
    }
    fenshu sub(fenshu a, fenshu b){
        return build(a.fz*b.fm-b.fz*a.fm, a.fm*b.fm);
    }
    fenshu multi(fenshu a, fenshu b){
        return build(a.fz*b.fz, a.fm*b.fm);
    }
    fenshu divi(fenshu a, fenshu b){
        return build(a.fz*b.fm, a.fm*b.fz);
    }
    int cmp(fenshu a, fenshu b){
        if(a.fz*b.fm>b.fz*a.fm){
            return 1;
        }
        else if(a.fz*b.fm==b.fz*a.fm){
            return 0;
        }
        else{
            return -1;
        }
    }
    fenshu abs(fenshu a){
        if(a.fz<0) a.fz=-a.fz;
        return a;
    }
    
    int main(){
        
        freopen("data.in", "r", stdin);
    
        for(int i=1; i<=3; i++){
    //        printf("输入函数%d的斜率和截距:", i);
            scanf("%d", &tp);
            if(tp==0){
                scanf("%d", &k[i].fz);
                k[i].fm=1;
            }
            else{
                scanf("%d/%d", &k[i].fz, &k[i].fm);
            }
            scanf("%d", &tp);
            if(tp==0){
                scanf("%d", &b[i].fz);
                b[i].fm=1;
            }
            else{
                scanf("%d/%d", &b[i].fz, &b[i].fm);
            }
        }
    /*    for(int i=0; i<3; i++){
            printf("%d/%d %d/%d
    ", k[i].fz, k[i].fm, b[i].fz, b[i].fm);
        }*/
    
        x12=divi(sub(b[2], b[1]), sub(k[1], k[2]));
        xmax=x12; xmin=x12;
        x23=divi(sub(b[3], b[2]), sub(k[2], k[3]));
        xmax=(cmp(xmax, x23)<0?x23:xmax);
        xmin=(cmp(xmin, x23)>0?x23:xmin);
        x13=divi(sub(b[3], b[1]), sub(k[1], k[3]));
        xmax=(cmp(xmax, x13)<0?x13:xmax);
        xmin=(cmp(xmin, x13)>0?x13:xmin);
    
        y12=add(multi(k[1], x12), b[1]);
        ymax=y12; ymin=y12;
        y23=add(multi(k[2], x23), b[2]);
        ymax=(cmp(ymax, y23)<0?y23:ymax);
        ymin=(cmp(ymin, y23)>0?y23:ymin);
        y13=add(multi(k[3], x13), b[3]);
        ymax=(cmp(ymax, y13)<0?y13:ymax);
        ymin=(cmp(ymin, y13)>0?y13:ymin);
    
    /*    printf("xmax:%d/%d
    ", xmax.fz, xmax.fm);
        printf("xmin:%d/%d
    ", xmin.fz, xmin.fm);
        printf("ymax:%d/%d
    ", ymax.fz, ymax.fm);
        printf("ymin:%d/%d
    ", ymin.fz, ymin.fm); */
    
        fenshu TwoFirst, Srect, S1213, S1323, S1223, Stri;
        TwoFirst.fz=2; TwoFirst.fm=1;
        Srect=multi(sub(xmax, xmin), sub(ymax, ymin));
        S1213=divi(multi(abs(sub(x12, x13)), abs(sub(y12, y13))), TwoFirst);
        S1323=divi(multi(abs(sub(x13, x23)), abs(sub(y13, y23))), TwoFirst);
        S1223=divi(multi(abs(sub(x12, x23)), abs(sub(y12, y23))), TwoFirst);
        Stri=sub(Srect, add(S1213, add(S1323, S1223)));
    
        if(Stri.fm==1){
            printf("%d
    ", Stri.fz);
        }
        else{
            printf("%d/%d
    ", Stri.fz, Stri.fm);
        }
    
        return 0;
    }
  • 相关阅读:
    u
    华为OJ:数字颠倒
    Unity3D &amp; C# 设计模式--23
    Cocos2d-x学习笔记(12)(CCControlSwitch开关、CCControlSlider滑动条、CCControlButtonbutton)
    hdu5299 Circles Game
    asp.net webform中使用async,await实现异步操作
    Restful风格wcf调用4——权限认证
    Restful风格wcf调用3——Stream
    Restful风格wcf调用2——增删改查
    Restful风格wcf调用
  • 原文地址:https://www.cnblogs.com/dong628/p/12077702.html
Copyright © 2011-2022 走看看