使用三个点(x,y),如何确定它是否是三角形

Using three points (x, y), How to find whether it is triangle or not

本文关键字:何确定 三角形 是否是 三个      更新时间:2023-10-16

我在codeforce中有一个作业,上面写着:
像所有问题解决者一样,埃布拉姆喜欢吃可丽饼!众所周知,绉纱通常呈三角形。现在埃布拉姆想知道可丽饼面能有多大!因此,他尝试使用三个点在平面上绘制一个三角形,并计算三角形三条边的最大长度。但有时他会睡着,因为他一直在忙于准备训练问题的团队!因此,他使用的三个点可能不会形成一个三角形,可以代表一块绉纸!三角形只有在具有正面积时才能表示一块绉纱。所以你是来帮助埃布拉姆的!给定 Ebram 使用的坐标,确定它们是否形成一个可以代表一块绉纱的三角形。

输入: 三个整数坐标 (X,Y),表示 Ebram 使用的三个点。每个点在单独的线上。

输出:如果这些点形成一个可以代表一块绉纱的三角形,请打印三角形三条边最大长度的正方形。否则打印"穷男孩">
示例

input 
1 1 
3 1 
3 9 
output 
68 


input 
-10 8 
9 100 
3 8 
output 
8825


input 
7 3 
3 3 
19 3 
output 
Poor boy 

这是我使用的代码:

#include <iostream>
#include <cmath>
using namespace std;
int main () {
double x1,y1,x2,y2,x3,y3;
double area;
double s1,s2,s3;
double slope1, slope2;
cin >> x1 >> y1;
cin >> x2 >> y2;
cin >> x3 >> y3;
slope1 =((y2-y1)/(x2-x1));
slope2 =((y3-y2)/(x3-x2));
area = 0.5*abs(((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1)));
if (slope1!=slope2 &&  (area)!=0){

s1 = sqrt(((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)));
s2 = sqrt(((x2-x3)*(x2-x3))+((y2-y3)*(y2-y3)));
s3 = sqrt(((x1-x3)*(x1-x3))+((y1-y3)*(y1-y3)));
if (s1 > s2 && s1 > s3)
cout<<s1*s1<<endl;
if (s2 > s1 && s2 > s3)
cout<<s2*s2<<endl;
if (s3 > s1 && s3 > s2)
cout <<s3*s3<<endl;
}
else
cout <<"Poor boy";
return 0;

}


首先,我找到斜率 1 和斜率 2 来检查三个点是否不在同一条线上。因此,如果它们不相等,则形成一个三角形(绉)。 使用这个:

slope1 =((y2-y1)/(x2-x1));
slope2 =((y3-y2)/(x3-x2));

然后我写了一个关系来用这个公式找到三角形的面积:

area = 0.5*abs(((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1)));

最后,我用 if 语句来查找它是否是一个三角形,并找到三角形每条边的长度,然后找到最大长度并打印它的正方形。

if (slope1!=slope2 &&  (area)!=0){

s1 = sqrt(((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)));
s2 = sqrt(((x2-x3)*(x2-x3))+((y2-y3)*(y2-y3)));
s3 = sqrt(((x1-x3)*(x1-x3))+((y1-y3)*(y1-y3)));
if (s1 > s2 && s1 > s3)
cout<<s1*s1<<endl;
if (s2 > s1 && s2 > s3)
cout<<s2*s2<<endl;
if (s3 > s1 && s3 > s2)
cout <<s3*s3<<endl;
}
else
cout <<"Poor boy";
return 0;

}


我在编译器中测试了代码,它完美地运行了示例中所示的 I/O。我在codeforce上提交了代码,但是在测试8中我卡错了答案,我不知道为什么?,并且我的代码可以很好地运行输入和输出。如果你帮助大家,我会很高兴。

与 Sani 的答案一样,我建议计算每对点之间的上升和运行:

rise1 = y2 - y1
rise2 = y3 - y2
rise3 = y1 - y3
run1 = x2 - x1
run2 = x3 - x2
run3 = x1 - x3

同样,我建议检查任何两点是否重合。请注意,这相当于 Sani 的代码正在检查的内容:

if (rise1 = run1 = 0) or (rise2 = run2 = 0) or (rise3 = run3 = 0) then
print "Poor Boy"
return 0

现在,与 Sani 类似,我们继续检查点是否在一条线上。但是,我们可以简化条件以稍微检查一下。请注意,如果垂直线上没有两个点,则如果任意两点之间的斜率相等,则三个点位于一条线上。也就是说,m1 = m2、m2 = m3 或 m3 = m1,等效。我们可以检查 m1 = m2。当rise1/run1 = rise2/run2时,这是正确的,这是安全的,因为我们假设垂直线上没有点。我们可以再次安全地将其重新排列为 rise1 * run2 = rise2 * run1。如果垂直线上没有两个点,这是我们唯一需要的检查。

如果两个点在一条垂直线上怎么办?然后 run1 和 run2 中至少有一个将为零。但是,由于我们已经保证没有两个点是重合的,因此我们可以绝对确定,如果其中任何一个为零,则相应的上升为非零。还有另外两种情况(除了垂直线上没有两个点):

  • 正好有两个点在一条垂直线上。然后,run1 或 run2(但不是两者)为零。在不损失通用性的情况下,假设 run1 为零。然后条件 rise1 * run2 = rise2 * run1 简化为 rise1 * run2 = 0。因为我们知道 rise1 不为零,所以只有当 run2 = 0 时才满足这一点,这与我们假设的情况相矛盾。这意味着,在这种情况下,我们之前推导的条件将产生正确的结果,并将点标识为不在同一条线上。

  • 三个点在垂直线上。然后 run1 和 run2 均为零。然后条件 rise1 * run2 = rise2 * run1 简化为 0 = 0,这始终为真。在这种情况下,条件将产生正确的结果,并将三个点标识为在同一条线上。

因为我们为垂直线上没有两个点的情况推导出的条件恰好为所有其他可能的情况产生正确的结果,所以我们可以在所有情况下使用它(假设没有两个点是重合的)。因此,除了 rise1 * run2 = rise2 * run1 之外,我们不需要检查任何内容:

if rise1 * run2 = rise2 * run1 then
print "Poor Boy"
return 0

现在我们知道我们有一个三角形,需要返回三条边中最大的一条。我们需要各自坐标的平方差之和。幸运的是,我们已经有了坐标差异,因此:

d1 = (rise1 * rise1) + (run1 * run1)
d2 = (rise2 * rise2) + (run2 * run2)
d3 = (rise3 * rise3) + (run3 * run3)
return max(d1, d2, d3)

您最大的问题是,在计算斜率时,您不断获得分母为 0 的输入division by 0。 即积分(3, 4), (3, 5) and (5, 6)将产生-1/0.

另一件事是你"过于复杂"的事情。

这是一个分步示例,以阐明如何处理此问题(即不是最佳代码):

// Check if any two points are the same. I.e. no triangle
if (x1 == x2 && y1 == y2 || x1 == x3 && y1 == y3 || x2 == x3 && y2 == y3) {
cout << "Poor boy";
return 0;
}
// Check if all points are on the same horizontal or vertical line
if (x1 == x2 && x1 == x3 || y1 == y2 && y1 == y3) {
cout << "Poor boy";
return 0;
}
// Calculate the nominators and denominators
nominator1 = y2-y1;
denominator1 = x2-x1;
nominator2 = y3-y2;
denominator2 = x3-x2;
nominator3 = y1-y3;
denominator3 = x1-x3;
// Calculate the slopes, if possible.
if (denominator1 == 0) slope1 = 0;
else slope1 = nominator1 / denominator1;
if (denominator2 == 0) slope2 = 0;
else slope2 = nominator2 / denominator2;
if (denominator3 == 0) slope3 = 0;
else slope3 = nominator3 / denominator3;
// Check if the three points form a triangle or a straight line.
// I.e. if all slopes are the same, it is a line.
if ((slope1 == slope2 && slope1 == slope3)) {
cout << "Poor boy";
return 0;
}
// Calculate the square of the length of each side
// (No abs is needed since a square of negative numbers is positive.)
// (Also no sqrt is needed since we're only interrested in the square of the longest side.)
side1 = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
side2 = (x3-x2)*(x3-x2) + (y3-y2)*(y3-y2);
side3 = (x1-x3)*(x1-x3) + (y1-y3)*(y1-y3);
// Note: This can be used instead which is the same calculation:
// side1 = denominator1 * denominator1 + nominator1 * nominator1;
// side2 = denominator2 * denominator2 + nominator2 * nominator2;
// side3 = denominator3 * denominator3 + nominator3 * nominator3;
// Get the longest side squared.
maxSide = side1 > side2 ? side1 > side3 ? side1 : side2 > side3 ? side2 : side3;
cout << maxSide;

免责声明:代码未经测试!