您的位置:首页 > 其它

URAL-1451. Beerhouse Tale

2017-09-04 09:35 302 查看
1、知识点:费马点

2、思路:下面是百度百科对费马点的解释,也是解题思路:

① 若三角形3个内角均小于120°,那么3条距离连线正好三等分费马点所在的周角,即该点所对三角形三边的张角相等,均为120°。所以三角形的费马点也称为三角形的等角中心。

(托里拆利的解法中对这个点的描述是:对于每一个角都小于120°的三角形ABC的每一条边为底边,向外作正三角形,然后作这三个正三角形的外接圆。托里拆利指出这三个外接圆会有一个共同的交点,而这个交点就是所要求的点。这个点和当时已知的三角形特殊点都不一样。这个点因此也叫做托里拆利点。)

② 若三角形有一内角大于等于120°,则此钝角的顶点就是距离和最小的点。

/*用途:
**说明:
**算法:
*/

//#define LOCAL
#include <cstdio>
#include <cmath>
using namespace std;
#define MAXN 3
#define PREC 0.00000001

struct point{
double x, y;
};

point poi[MAXN];
point ans;

int main()
{
#ifdef LOCAL
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
#endif

for(int i=0; i<MAXN; i++)
scanf("%lf %lf", &(poi[i].x), &(poi[i].y));

double c, b, a;  //AB、AC、BC对应三边
a = sqrt(pow(poi[1].x-poi[2].x, 2) + pow(poi[1].y-poi[2].y, 2));
b = sqrt(pow(poi[0].x-poi[2].x, 2) + pow(poi[0].y-poi[2].y, 2));
c = sqrt(pow(poi[0].x-poi[1].x, 2) + pow(poi[0].y-poi[1].y, 2));

double cosA, cosB, cosC;
cosA = (b*b+c*c-a*a) / (2*b*c);
cosB = (a*a+c*c-b*b) / (2*a*c);
cosC = (a*a+b*b-c*c) / (2*a*b);

//任意角>=120度
if(cosA <= -0.5){
printf("%.8lf %.8lf", poi[0].x, poi[0].y);
return 0;
}
else if(cosB <= -0.5){
printf("%.8lf %.8lf", poi[1].x, poi[1].y);
return 0;
}
else if(cosC <= -0.5){
printf("%.8lf %.8lf", poi[2].x, poi[2].y);
return 0;
}

point or_c, or_c1, or_c2, or_b, or_b1, or_b2;
point mid_c, mid_b;
mid_c.x = (poi[0].x+poi[1].x) / 2;
mid_c.y = (poi[0].y+poi[1].y) / 2;
mid_b.x = (poi[0].x+poi[2].x) / 2;
mid_b.y = (poi[0].y+poi[2].y) / 2;

double k_AB, k_AC;
k_AB = (poi[0].y-poi[1].y) / (poi[0].x-poi[1].x);
k_AC = (poi[0].y-poi[2].y) / (poi[0].x-poi[2].x);

//求AB边外接圆心
if(fpclassify(k_AB) == FP_INFINITE){    //k_AB不存在
or_c1.x = mid_c.x - c/sqrt(12);
or_c1.y = mid_c.y;
or_c2.x = mid_c.x + c/sqrt(12);
or_c2.y = mid_c.y;
}
else if(k_AB == 0){   //k_AB=0
or_c1.x = mid_c.x;
or_c1.y = mid_c.y + c/sqrt(12);
or_c2.x = mid_c.x;
or_c2.y = mid_c.y - c/sqrt(12);
}
else{   //k_AB存在 且不为0
or_c1.x = mid_c.x - c/sqrt(12)*k_AB/sqrt(k_AB*k_AB+1);
or_c1.y = mid_c.y - 1.0/k_AB*(or_c1.x-mid_c.x);
or_c2.x = mid_c.x + c/sqrt(12)*k_AB/sqrt(k_AB*k_AB+1);
or_c2.y = mid_c.y - 1.0/k_AB*(or_c2.x-mid_c.x);
}

double v1 = (or_c1.x-mid_c.x)*(poi[2].x-poi[0].x) + (or_c1.y-mid_c.y)*(poi[2].y-poi[0].y);
if(v1 < PREC){      //如果or_c1在三角形外部
or_c.x = or_c1.x;
or_c.y = or_c1.y;
}
else{
or_c.x = or_c2.x;
or_c.y = or_c2.y;
}

//求AC边外接圆心
if(fpclassify(k_AC) == FP_INFINITE){   //k_AC不存在
or_b1.x = mid_b.x - b/sqrt(12);
or_b1.y = mid_b.y;
or_b2.x = mid_b.x + b/sqrt(12);
or_b2.y = mid_b.y;
}
else if(k_AC == 0){
or_b1.x = mid_b.x;
or_b1.y = mid_b.y + b/sqrt(12);
or_b2.x = mid_b.x;
or_b2.y = mid_b.y - b/sqrt(12);
}
else{   //k_AC存在
or_b1.x = mid_b.x - b/sqrt(12)*k_AC/sqrt(k_AC*k_AC+1);
or_b1.y = mid_b.y - 1.0/k_AC*(or_b1.x-mid_b.x);
or_b2.x = mid_b.x + b/sqrt(12)*k_AC/sqrt(k_AC*k_AC+1);
or_b2.y = mid_b.y - 1.0/k_AC*(or_b2.x-mid_b.x);
}

double v2 = (or_b1.x-mid_b.x)*(poi[1].x-poi[0].x) + (or_b1.y-mid_b.y)*(poi[1].y-poi[0].y);
if(v2 < PREC){      //如果or_b1在三角形外部
or_b.x = or_b1.x;
or_b.y = or_b1.y;
}
else{
or_b.x = or_b2.x;
or_b.y = or_b2.y;
}

//求经过or_b,or_c 两点的直线,并求点A关于直线的对称点
double k_oo = (or_b.y-or_c.y) / (or_b.x-or_c.x);
if(fpclassify(k_oo) == FP_INFINITE){    //如果圆心连线斜率不存在
ans.x = 2*or_b.x - poi[0].x;
ans.y = poi[0].y;
}
else if(fabs(k_oo) < PREC){     //如果斜率为0
ans.x = poi[0].x;
ans.y = 2*or_b.y - poi[0].y;
}
else{                           //斜率存在且不为0
ans.x = (2*poi[0].y+(1.0/k_oo-k_oo)*poi[0].x-2*(or_c.y-k_oo*or_c.x)) / (k_oo+1.0/k_oo);
ans.y = poi[0].y-1.0/k_oo*(ans.x-poi[0].x);
}

printf("%.8lf %.8lf", ans.x, ans.y);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: