新手光能
@候平仄
全文自创,喷子请住嘴。
今天正好有空,然后就解出了这个问题
其实并不是特别难,暴力即可。
先介绍一下费马点是什么(在这里,我们只考虑三角形中的费马点问题,因为四边形的太简单,后面的需要用最短路暴力解)
费马点是三角形内部一点,使得它到三角形的三个顶点的长度之和最短。
那怎么求嫩?
如图:
A的对边为a,B的对边为b,C的对边为c,已知三边长度
我们先在三角形中找出任意一点P,连线
然后把三角形APB旋转逆时针六十度,然后得到一个奇怪的东西
注意到三角形APF是等边三角形(∠PAF=60,AP=AF)
所以AP=PF
那AP+BP+CP就转化成了CP+PF+EF
两点之间线端最短,所以AP+BP+CP=CP+PF+EF≤CE(C和E的直接连线)
所以费马点一定在CE上。再把APC旋转出去,做同样的操作,两线的交点就是费马点。
刘景程在2020-08-31 10:43:46追加了内容
但是有必要这么麻烦吗?
换一个图(接下来均以此图为准):
三角形MCA也是正三角形,(CA=CM,MCA=60)
如果P是费马点的话,PHMB一定共线使得长度最短,原理同上。
两个等边三角形的顶点与其各自的对点的连线交点就是费马点,同时使得两条线最短。
现在,问题就是算出两个顶点了
刘景程在2020-08-31 10:45:10追加了内容
@赵逸凡 因为是旋转60度啊,他的那个夹角的角度也必须是六十度(你没学过?)
刘景程在2020-08-31 10:54:21追加了内容
以C点为原点建系
先把点a的坐标算出来
先做一条垂线
设CH=l(这个叫作le huaji),HB=a-l
勾股一下可以得到b²-l²=AH²=c²-(a-l)²,然后解出来l=(b²-c²+a²)/2a,这是A的横坐标
纵坐标就是根号下的b²-l²
顺便一写:B(0,a),C(0,0)
刘景程在2020-08-31 11:01:16追加了内容
介绍一下三角函数
必须在直角的情况下才能使用
还有反三角函数,比较重要(但我不想写),自行度娘
刘景程在2020-08-31 11:16:04追加了内容
费马点的计算要分两种情况
有角大于120时,那两个等边三角形的连线交点在三角形外,不是费马点,所以费马点是三角形的顶点之一
接下来算M点坐标
还是做垂线
A的对边是a,以此类推
用三角函数的余弦公式可以算出∠ACB=acos(反三角函数)((a²+b²-c²)/2ab)
当acb<30度时,M在第一象限,MCE=ACB+60
当acb>30时,M在第二象限,MCE=180-60-ACB=120-ACB
MC=AC=a
三角函数得出ME=sin(MCE)*a,EC=cos(MCE)*a
得出M的坐标
刘景程在2020-08-31 11:20:02追加了内容
D的坐标很好求,三线合一,横坐标是a/2,勾股得纵坐标=(根号0.75)*a
作AD的函数和MB的函数,两条函数的交点就是费马点
刘景程在2020-08-31 11:20:52追加了内容
代码:
#include<bits/stdc++.h>
using namespace std;
struct point
{
double x;
double y;
};
struct f
{
double k;
double b;
//y=kx+b
};
point across(f a,f b)
{
point res;
res.x=(a.b-b.b)/(b.k-a.k);
res.y=res.x*a.k+a.b;
return res;
}
f make_function(point a,point b)
{
f res;
res.k=(a.y-b.y)/(a.x-b.x);
res.b=a.y-a.x*res.k;
return res;
}
int main()
{
double a,b,c;
cin>>a>>b>>c;
point A,B,C;
C.x=0;
C.y=0;
B.x=a;
B.y=0;
double l=(a*a+b*b-c*c)/(2*a);
A.x=l;
A.y=sqrt(b*b-l*l);
//cout<<acos((b*b+c*c-a*a)/(2*b*c))<<" "<<acos((a*a+b*b-c*c)/(2*a*b))<<" "<<acos((a*a-b*b+c*c)/(2*a*c))<<endl;
if(acos((b*b+c*c-a*a)/(2*b*c))*180.0/M_PI>120.0||acos((a*a+b*b-c*c)/(2*a*b))*180.0/M_PI>120.0||acos((a*a-b*b+c*c)/(2*a*c))*180.0/M_PI>120.0)
{
if(a+b<b+c&&a+b<a+c)
{
cout<<C.x<<" "<<C.y;
}
if(a+c<a+b&&a+c<b+c)
{
cout<<B.x<<" "<<B.y;
}
if(b+c<a+b&&b+c<a+c)
{
cout<<A.x<<" "<<A.y;
}
return 0;
}
double ACB=acos((a*a+b*b-c*c)/(2.0*a*b))*180.0/M_PI;
cout<<ACB<<endl;
point M;
if(ACB<30.0)
{
double MCN=ACB+60.0;
double n=cos(MCN)*b*180.0/M_PI,m=sin(MCN)*b*180.0/M_PI;
M.y=m;
M.x=n;
}
else
{
double MCN=120.0-ACB;
double n=cos(MCN*M_PI/180)*b,m=sin(MCN*M_PI/180)*b;
cout<<n<<' '<<m<<" "<<MCN<<endl;
M.y=m;
M.x=-n;
}
f f1=make_function(M,B);
point D;
D.x=a/2.0;
D.y=-sqrt(0.75)*a;
//cout<<A.x<<" "<<A.y<<endl<<B.x<<" "<<B.y<<endl<<C.x<<" "<<C.y<<endl<<M.x<<" "<<M.y<<endl<<D.x<<" "<<D.y<<endl;
f f2=make_function(D,A);
point ans=across(f1,f2);
cout<<ans.x<<" "<<ans.y;
}
/*
5.58 3.63 4.68
*/
自行验证
刘景程在2020-08-31 11:22:24追加了内容
以后有时间的话我会再写一篇博客,今天主要是有点赶时间,不是太友好,有点粗糙
以后一定会重新写一篇
以后有时间的话我会再写一篇博客,今天主要是有点赶时间,不是太友好,有点粗糙
以后一定会重新写一篇
以后有时间的话我会再写一篇博客,今天主要是有点赶时间,不是太友好,有点粗糙
以后一定会重新写一篇
以后有时间的话我会再写一篇博客,今天主要是有点赶时间,不是太友好,有点粗糙
以后一定会重新写一篇
初级启示者
但对于P点的任意一点性质,我感觉首先你要保证∠PAF=60°以及∠APB的补角是60°
还有,请问为什么要将∠APB逆时针旋转60°?
顺便问一下,多边形(五边形、六边形)如何最短路暴力求解?(假设不是网格图,且要求出非常准确的解)
初级启示者
我搜了一下多边形费马点,一看,数学学术论文,而且某lz说多边形费马点他也不会用编程求
我看了下多边形费马点证明,我的天,7页多张纸,而且需要引用物理的力学三角架模型来做
赵逸凡在2020-08-31 11:08:53追加了内容
感觉可以瞎推一个结论:
对于一个n边形且满足
必定无法用编程求出准确的费马点坐标(doge)
但是我们可以呼叫张带数学家
@张曈 @张曈
初级守护
???????????????????????????????????????????????????????
???????????????????????????????????????????????????????
???????????????????????????????????????????????????????