餘弦定理的證明及其應用 改進版

我之前寫過一個餘弦定理的證明及其應用的博客,但是因爲那時候自己特別的菜,而且原博客沒有加LaTeX\LaTeX,而且很多地方有描述不明確的地方,現在來修一下

還是那張圖,來自百度百科
在這裏插入圖片描述
餘弦定理的內容是,對於任意一個三角形,滿足
a2=b2+c22bccosAb2=a2+c22accosBc2=a2+b22abcosCa^2=b^2+c^2-2bc\cdot \cos A \\ b^2=a^2+c^2-2ac\cdot \cos B \\ c^2=a^2+b^2-2ab\cdot \cos C
證明其實很簡單
上面那個圖裏面就能看出來
AB=c,BD=ccosB,AD=csinB,CD=accosB,RtΔADCc2sin2B+(accosB)2=b2c2sin2B+a22accosB+c2sin2B=b2a2+c22accosB=b2\because AB=c,BD=c\cdot \cos B,AD=c\cdot \sin B,CD=a-c\cdot \cos B,\text{Rt}_\Delta ADC \\ \therefore c^2\cdot \sin^2 B+(a-c\cdot \cos B)^2=b^2 \\ c^2\cdot \sin^2B+a^2-2ac\cdot \cos B+c^2\cdot\sin^2B=b^2 \\ a^2+c^2-2ac\cdot\cos B=b^2

另外兩個也同理
當然,還有一種非常簡便的證法,是利用向量(vectorvector)解決的
向量,手寫體記做a\vec{a},打印體有時也記做a
向量內積,ab=abcosθ\vec{a}\cdot\vec{b}=|\vec{a}|\cdot|\vec{b}|\cdot\cos\theta
其中θ\theta表示兩個向量的夾角,不懂可以百度優先搜索,話說這個高中課本上會講吧

在這裏插入圖片描述
我們把他重新定向一下,那麼
a+b=ca=cba2=(cb)2a2=b2+c22bca2=b2+c22bccosθa2=b2+c22bccosθ\vec{a}+\vec{b}=\vec{c} \\ \vec{a}=\vec{c}-\vec{b} \\ \vec{a}^2=(\vec{c}-\vec{b})^2 \\ |\vec{a}|^2=|\vec{b}|^2+|\vec{c}|^2-2\vec{b}\cdot\vec{c} \\ a^2=b^2+c^2-2|\vec{b}|\cdot|\vec{c}|\cdot \cos\theta \\ a^2=b^2+c^2-2bc\cdot\cos\theta

其它的也一樣,我不會告訴你我theta角標錯了因爲是盜的圖


餘弦定理是解三角形中的一個非常重要的定理,配合正弦定理應用可以解決對任意三角形知三求三的問題,是非常重要的一個定理


那麼餘弦定理在OI中又有什麼應用呢?

題目描述(這裏不是向量…)
有一條豪華遊輪(其實就是條小木船),這種船可以執行44種指令:

rightright XX : 其中XX是一個11719719的整數,這個命令使得船順時針轉動X度。

leftleft XX : 其中XX是一個11719719的整數,這個命令使得船逆時針轉動X度。

forwardforward XX : 其中XX是一個整數(1110001000),使得船向正前方前進X的距離。

backwardbackward XX : 其中XX是一個整數(1110001000),使得船向正後方前進X的距離。

隨意的寫出了nn個命令,找出一個種排列命令的方法,使得船最終到達的位置距離起點儘可能的遠。

輸入輸出格式
輸入格式:
第一行一個整數nn(1n501 \leq n \leq 50),表示給出的命令數。

接下來nn行,每行表示一個命令。

輸出格式:
一個浮點數,能夠走的最遠的距離,四捨五入到66位小數。

這道題我們看到之後很快就能夠反映出來,這個地方需要做一個貪心

因爲多次拐彎肯定比一次的要近,所以我們讓forwardforward走完,然後儘量轉180180度,然後把backwardbackward走完,這時候起點和終點之間的距離就是要算的答案了

那麼我們怎麼來算他能最多轉多少度才能讓這個度數和180180度的差最小呢?
我們可以運用揹包的思想
f[i][j]f[i][j]表示前i個轉圈的指令,能不能轉到j度,轉移其實很簡單,大概是這樣的:

	for(int i=1,i<=anglecnt;i++)
		for(int j=0;j<=360;j++){
			if(f[i-1][j]){
				f[i][j]=true;
				f[i][(j+angle[i]+360)%360]=true;
			}
		}

那好了,我們現在知道了旋轉角度,知道了兩邊的邊長,那麼我們就可以使用餘弦定理了啊

printf("%.6lf\n",sqrt(a*a+b*b-2*a*b*cos(degree*pi/180)));

注意C++C++中三角函數運用的是弧度制

全代碼大概是這樣的

# include <cstdio>
# include <algorithm>
# include <cstring>
# include <cmath>
# include <climits>
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)

using namespace std;

const int N=55;
const double pi=3.14159265358979;
int n,go,back,angle[N],a,b,degree=INT_MAX;
bool f[N][1005];
char s[N];
int main()
{
	scanf("%d",&n);
	Rep(i,1,n){
		int x;
		scanf("%s%d",s,&x);
		if(s[0]=='f') a+=x;
		if(s[0]=='b') b+=-x;
		if(s[0]=='l') angle[++angle[0]]=x;
		if(s[0]=='r') angle[++angle[0]]=-x; 
	}
	f[0][0]=true;
	Rep(i,1,angle[0])
		Rep(j,0,360){
			if(f[i-1][j]){
				f[i][j]=true;
				f[i][(j+angle[i]+360)%360]=true;
			}
		}
	Rep(i,0,360)
		if(f[angle[0]][i]) degree=min(degree,abs(180-i));
	printf("%.6lf\n",sqrt(a*a+b*b-2*a*b*cos(degree*pi/180)));
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章