1 条题解
-
0
三角形分类
一个自然的想法,和它的麻烦
给出三条线段,先判断能否构成三角形,再判断形状。直接按定义来:任意两边之和大于第三边——那要比较三种组合(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 ✓
容易出错的细节
- 等腰和等边必须用并列的两个 if:等边三角形同时是等腰三角形,样例
3 3 3要求输出三行。写成 if / else if 的话,等边时只输出 Equilateral 一行,第一个样例就错了。 - 不排序直接比角度会错:
6 10 6这种最长边在中间的数据,不排序根本不知道该拿哪两条边算平方和。 - 比较平方用整数乘法即可,不要用
sqrt开方后再比较——浮点有精度风险,还多此一举。
复杂度
固定 3 次交换、数次比较,时间与空间复杂度均为 O(1)。
这题的本质:排序把复杂问题化简——排好序之后,"任意两边"塌缩成"两条短边与最长边",判断数量从三种组合变成一次比较。
- 1
信息
- ID
- 522
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 8
- 已通过
- 3
- 上传者