因为这篇文章写得时候我特别菜,还不会 LaTeX \LaTeX LATEX,而且表述中又不少不是很明确的地方,大家可以看余弦定理的证明及其应用 改进版以追求更好的阅读体验qwq
余弦定理
余弦定理,顾名思义,与余弦函数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
得证
其实余弦定理和勾股定理一样,都有很多种证明方法,但是最常用的还是这两种
其实是我不会
余弦定理的应用
讲完了证明,我们来看看余弦定理的应用
题目描述(这里不是向量…)
有一条豪华游轮(其实就是条小木船),这种船可以执行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;
}