问题标题: 酷町堂:对候平仄同学的费马点问题的解答

7
13
刘景程
刘景程
新手光能
新手光能

@候平仄​​​​​​​

全文自创,喷子请住嘴。

今天正好有空,然后就解出了这个问题

其实并不是特别难,暴力即可。

先介绍一下费马点是什么(在这里,我们只考虑三角形中的费马点问题,因为四边形的太简单,后面的需要用最短路暴力解)

费马点是三角形内部一点,使得它到三角形的三个顶点的长度之和最短。

那怎么求嫩?

如图:

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追加了内容

以后有时间的话我会再写一篇博客,今天主要是有点赶时间,不是太友好,有点粗糙

以后一定会重新写一篇

 

以后有时间的话我会再写一篇博客,今天主要是有点赶时间,不是太友好,有点粗糙

以后一定会重新写一篇

 

以后有时间的话我会再写一篇博客,今天主要是有点赶时间,不是太友好,有点粗糙

以后一定会重新写一篇

 

以后有时间的话我会再写一篇博客,今天主要是有点赶时间,不是太友好,有点粗糙

以后一定会重新写一篇


0
0
0
朱优扬
朱优扬
中级天翼
中级天翼

我怀疑我上的学是假的

0
赵逸凡
赵逸凡
初级启示者
初级启示者

但对于P点的任意一点性质,我感觉首先你要保证∠PAF=60°以及∠APB的补角是60°

还有,请问为什么要将∠APB逆时针旋转60°?

顺便问一下,多边形(五边形、六边形)如何最短路暴力求解?(假设不是网格图,且要求出非常准确的解)

0
赵逸凡
赵逸凡
初级启示者
初级启示者

我搜了一下多边形费马点,一看,数学学术论文,而且某lz说多边形费马点他也不会用编程求

我看了下多边形费马点证明,我的天,7页多张纸,而且需要引用物理的力学三角架模型来做

赵逸凡在2020-08-31 11:08:53追加了内容

感觉可以瞎推一个结论:

对于一个n边形且满足

必定无法用编程求出准确的费马点坐标(doge)

但是我们可以呼叫张带数学家

@张曈 @张曈 

 

 

0
夏梓轩
夏梓轩
初级守护
初级守护

???????????????????????????????????????????????????????

???????????????????????????????????????????????????????

???????????????????????????????????????????????????????

0
侯平仄
侯平仄
新手天翼
新手天翼

膜拜大佬Orz,谢谢刘大佬

/fad

0
0
0
丁博扬
丁博扬
中级天翼
中级天翼

膜拜大佬

大佬好 大佬好 大佬好

丁博扬在2020-12-28 16:33:50追加了内容

硬是没看懂

0
0
0
0
0
王子逸
王子逸
新手天翼
新手天翼

你们在说什么?????
物理?
我怀疑我上的不是学!!!

0
李泽远
李泽远
高级天翼
高级天翼

Orz,请问楼主是怎么想到这种方法的?!

奇怪的方法增加了!

0
包涵宇
包涵宇
中级天翼
中级天翼

额,没看懂。。。(呵呵)

0
0
0
我要回答