1 条题解

  • 0
    @ 2026-10-8 21:09:26

    三角形分类

    一个自然的想法,和它的麻烦

    给出三条线段,先判断能否构成三角形,再判断形状。直接按定义来:任意两边之和大于第三边——那要比较三种组合(a+b>c、a+c>b、b+c>a);判断角度,又要知道哪条边最长。分支会写得又多又乱。

    突破口:先排序,再判断

    把三条边从小到大排成 a ≤ b ≤ c,情况立刻简化:

    • 最长边就是 c。构成三角形的条件"任意两边之和大于第三边"等价于只看一条:a + b > c——只要两条短边之和能超过最长边,另两种组合自动成立。
    • 判断角度只需要比较 a² + b² 与 c²(勾股定理的逆用):大于为锐角,等于为直角,小于为钝角。

    排序用三次两两交换即可,写法和"三位数排序"一题完全相同。

    代码实现

    #include <stdio.h>
    
    int main() {
        int a, b, c, t;
        scanf("%d%d%d", &a, &b, &c);
        /* 排序,保证 a <= b <= c */
        if (a > b) { t = a; a = b; b = t; }
        if (a > c) { t = a; a = c; c = t; }
        if (b > c) { t = b; b = c; c = t; }
        /* 能否构成三角形:只需判断两条短边之和 */
        if (a + b <= c) {
            printf("Not triangle\n");
            return 0;
        }
        /* 按角度分类:三种情况互斥,if / else if / else */
        if (a * a + b * b > c * c)
            printf("Acute triangle\n");
        else if (a * a + b * b == c * c)
            printf("Right triangle\n");
        else
            printf("Obtuse triangle\n");
        /* 按边分类:等腰与等边是并列判断,不是 else if */
        if (a == b || b == c)
            printf("Isosceles triangle\n");
        if (a == c)
            printf("Equilateral triangle\n");
        return 0;
    }
    

    用样例验证:

    • 3 3 3:排序后 3 3 3;9 + 9 > 9 → Acute;a == b → Isosceles;a == c → Equilateral,三行输出 ✓
    • 3 4 5:9 + 16 = 25 → Right,无相等边,一行 ✓
    • 6 10 6:排序后 6 6 10;36 + 36 < 100 → Obtuse;a == b → Isosceles,两行 ✓
    • 1 14 5:排序后 1 5 14;1 + 5 < 14 → Not triangle ✓

    容易出错的细节

    1. 等腰和等边必须用并列的两个 if:等边三角形同时是等腰三角形,样例 3 3 3 要求输出三行。写成 if / else if 的话,等边时只输出 Equilateral 一行,第一个样例就错了。
    2. 不排序直接比角度会错:6 10 6 这种最长边在中间的数据,不排序根本不知道该拿哪两条边算平方和。
    3. 比较平方用整数乘法即可,不要用 sqrt 开方后再比较——浮点有精度风险,还多此一举。

    复杂度

    固定 3 次交换、数次比较,时间与空间复杂度均为 O(1)。

    这题的本质:排序把复杂问题化简——排好序之后,"任意两边"塌缩成"两条短边与最长边",判断数量从三种组合变成一次比较。

    信息

    ID
    522
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    8
    已通过
    3
    上传者