UVa 376 More Triangles THE AMBIGUOUS CASE
题目描述
三角学中的歧义情况(ambiguous case\texttt{ambiguous case}ambiguous case)是指在已知两边和其中一边的对角时求解三角形。你需要编写一个程序,接收这样的数据并报告所有解。
输入格式
每行包含三个实数:前两个表示三角形的两边长度,第三个表示与第二边相对的角(以度为单位)。输入以0.0 0.0 0.0结束。
输出格式
对于每个数据,报告解的数量。如果有解,报告对应的第三边长度(保留两位小数)。如果有两个解,按递减顺序输出。无解时输出000。
样例输入
2.00 2.00 30.00 2.00 3.00 130.00 1.00 1.00 90.00 698.64 217.77 5.52 0.00 0.00 0.00样例输出
Case A B THETA # of Side Side # side side (deg) Triags 1 2 1 2.00 2.00 30.00 1 3.46 2 2.00 3.00 130.00 1 1.29 3 1.00 1.00 90.00 0 4 698.64 217.77 5.52 2 902.54 488.26 END OF REPORT for 4 cases题目分析
问题的本质
这是一个解三角形问题。已知两边aaa、bbb和边bbb的对角BBB,求解第三边ccc的长度。
已知条件
- 边aaa:第一条边的长度
- 边bbb:第二条边的长度(对角为BBB)
- 角BBB:边bbb的对角(以度为单位)
需要求解第三边ccc的可能长度。
余弦定理的应用
由余弦定理,边bbb满足:
b2=a2+c2−2accosB b^2 = a^2 + c^2 - 2ac\cos Bb2=a2+c2−2accosB
将其整理为关于ccc的一元二次方程:
c2−(2acosB)⋅c+(a2−b2)=0 c^2 - (2a\cos B) \cdot c + (a^2 - b^2) = 0c2−(2acosB)⋅c+(a2−b2)=0
记:
Δ=(2acosB)2−4(a2−b2)=4(b2−a2sin2B) \Delta = (2a\cos B)^2 - 4(a^2 - b^2) = 4(b^2 - a^2\sin^2 B)Δ=(2acosB)2−4(a2−b2)=4(b2−a2sin2B)
则方程的解为:
c=acosB±b2−a2sin2B c = a\cos B \pm \sqrt{b^2 - a^2\sin^2 B}c=acosB±b2−a2sin2B
歧义情况的分类
根据判别式和根的正负性,解的情况分为以下几类:
情况 1:BBB为锐角
- 如果b<asinBb < a\sin Bb<asinB:Δ<0\Delta < 0Δ<0,无解
- 如果b=asinBb = a\sin Bb=asinB:Δ=0\Delta = 0Δ=0,一个解(直角三角形),此时c=acosBc = a\cos Bc=acosB
- 如果b>asinBb > a\sin Bb>asinB:Δ>0\Delta > 0Δ>0,两个正根:
- 若b≥ab \ge ab≥a,两根均为正,但其中一根为acosB−⋯a\cos B - \sqrt{\cdots}acosB−⋯可能为负,需进一步判断,实际只有一个有效解
- 若b<ab < ab<a,两根均为正,两个有效解
情况 2:BBB为钝角
此时cosB<0\cos B < 0cosB<0,acosBa\cos BacosB为负数。两根中acosB−⋯a\cos B - \sqrt{\cdots}acosB−⋯为负,舍去;acosB+⋯a\cos B + \sqrt{\cdots}acosB+⋯可能为正也可能为负:
- 如果b≤ab \le ab≤a:无解
- 如果b>ab > ab>a:一个正解
情况 3:B=90∘B = 90^\circB=90∘
此时cosB=0\cos B = 0cosB=0,sinB=1\sin B = 1sinB=1,方程简化为c2=b2−a2c^2 = b^2 - a^2c2=b2−a2:
- 如果b≤ab \le ab≤a:无解
- 如果b>ab > ab>a:一个解c=b2−a2c = \sqrt{b^2 - a^2}c=b2−a2
参考代码
// More Triangles THE AMBIGUOUS CASE// UVa ID: 376// Verdict: Accepted// Submission Date: 2016-07-08// UVa Run Time: 0.050s//// 版权所有(C)2016,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;constdoublePI=2.0*acos(0.0);constdoubleEPSILON=1e-7;intmain(intargc,char*argv[]){ios::sync_with_stdio(false);intcases=0;doublea,b,B;vector<tuple<int,double,double,double,double,double>>triangles;while(cin>>a>>b>>B){if(fabs(a)+fabs(b)+fabs(B)<EPSILON)break;// B 为 0 或 180 度if(fabs(B)<=EPSILON||fabs(B-180.0)<=EPSILON){triangles.push_back({++cases,a,b,B,a+b,fabs(a-b)});continue;}// 零长度边if(a<EPSILON||b<EPSILON){triangles.push_back({++cases,a,b,B,-1.0,-1.0});continue;}doubleangle=B;doubleradB=B*PI/180.0;if(angle<90.0-EPSILON){// 锐角doubleh=a*sin(radB);if(b<h-EPSILON){triangles.push_back({++cases,a,b,angle,-1.0,-1.0});}elseif(fabs(b-h)<=EPSILON){triangles.push_back({++cases,a,b,angle,a*cos(radB),-1.0});}else{if(b>=a-EPSILON){doubleA=asin(a*sin(radB)/b);doubleC=PI-A-radB;doublec=sqrt(a*a+b*b-2*a*b*cos(C));triangles.push_back({++cases,a,b,angle,c,-1.0});}else{doubleoffset=sqrt(b*b-a*a*sin(radB)*sin(radB));doublec1=a*cos(radB)+offset;doublec2=a*cos(radB)-offset;if(c1<c2)swap(c1,c2);triangles.push_back({++cases,a,b,angle,c1,c2});}}}elseif(angle>90.0+EPSILON){// 钝角if(b<a-EPSILON){triangles.push_back({++cases,a,b,angle,-1.0,-1.0});}else{doubleA=asin(a*sin(radB)/b);doubleC=PI-A-radB;doublec=sqrt(a*a+b*b-2*a*b*cos(C));triangles.push_back({++cases,a,b,angle,c,-1.0});}}else{// 直角if(b<=a+EPSILON){triangles.push_back({++cases,a,b,angle,-1.0,-1.0});}else{triangles.push_back({++cases,a,b,angle,sqrt(b*b-a*a),-1.0});}}}// 输出表头cout<<"Case A B THETA # of Side Side"<<endl;cout<<" # side side (deg) Triags 1 2"<<endl;// 输出结果for(auto&t:triangles){intidx=get<0>(t);doublesideA=get<1>(t);doublesideB=get<2>(t);doubletheta=get<3>(t);doublec1=get<4>(t);doublec2=get<5>(t);cout<<setw(4)<<right<<idx;cout<<setw(7)<<right<<fixed<<setprecision(2)<<sideA;cout<<setw(7)<<right<<fixed<<setprecision(2)<<sideB;cout<<setw(7)<<right<<fixed<<setprecision(2)<<theta;cout<<setw(6)<<right<<((c1>0.0)+(c2>0.0));if(c1>0.0)cout<<setw(9)<<right<<fixed<<setprecision(2)<<c1;if(c2>0.0)cout<<setw(7)<<right<<fixed<<setprecision(2)<<c2;cout<<endl;}cout<<endl;cout<<"END OF REPORT for "<<cases<<" cases"<<endl;return0;}