余弦定理的证明及其应用

余弦定理

余弦定理,顾名思义,与余弦函数cos有关,具体的是这样的

在这里插入图片描述
对于任意一个三角形ABC,有如下结论

a2=b2+c2-2bc·cosA
b2=a2+c2-2ac·cosB
c2=a2+b2-2ab·cosC

为什么呢?

余弦定理的证明

在上面那张图中其实大家就能看到证明方法

根据三角函数,BD=c·cosB,AD=c·sinB
那么DC=a-c·cosB
接下来,根据勾股定理,我们就可以得到
b2=(c·sinB)2+(a-c·cosB)2
b2=c2·(sinB)2+a2+c2·(cosB)2-2ac·cosB
b2=a2+c2·(sinB2+cosB2)-2ac·cosB
b2=a2+c2-2ac·cosB

当然,这种方法计算量就“比较”大
个人认为使用向量更简单一点

向量:有向的线段,向量AC打印体记做AC 具体的大家可以参阅百度百科

在这里插入图片描述
首先,我们根据向量的加法,得到等式
a+b=c
a=c-b
a2=(c-b)2
a2=b2+c2-2·b·c
a2=b2+c2-2|b|·|c|·cosA (向量的数量积)
a2=b2+c2-2bc·cosA
得证

其实余弦定理和勾股定理一样,都有很多种证明方法,但是最常用的还是这两种
其实是我不会

余弦定理的应用

讲完了证明,我们来看看余弦定理的应用

扫描二维码关注公众号,回复: 8821009 查看本文章

洛谷p2625 豪华游轮

题目描述(这里不是向量…)
有一条豪华游轮(其实就是条小木船),这种船可以执行4种指令:

right X : 其中X是一个1到719的整数,这个命令使得船顺时针转动X度。

left X : 其中X是一个1到719的整数,这个命令使得船逆时针转动X度。 forward X : 其中X是一个整数(1到1000),使得船向正前方前进X的距离。

backward X : 其中X是一个整数(1到1000),使得船向正后方前进X的距离。

随意的写出了n个命令,找出一个种排列命令的方法,使得船最终到达的位置距离起点尽可能的远。

输入输出格式
输入格式:
第一行一个整数n(1 <= n <= 50),表示给出的命令数。

接下来n行,每行表示一个命令。

输出格式:
一个浮点数,能够走的最远的距离,四舍五入到6位小数。

这道题我们看到之后很快就能够反映出来,这个地方需要做一个贪心

因为多次拐弯肯定比一次的要近,所以我们让forward走完,然后尽量转180度,然后把backward走完,这时候起点和终点之间的距离就是要算的答案了

那么我们怎么来算他能最多转多少度才能让这个度数和180度的差最小呢?
我们可以运用背包的思想
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)));

这里运用的是弧度制,如果不理解的话可以上网去搜一搜

全代码大概是这样的

# 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;
}
发布了18 篇原创文章 · 获赞 3 · 访问量 1266

猜你喜欢

转载自blog.csdn.net/devout_/article/details/90924660