Project Euler 102

Project Euler 102

题目

Triangle containment

Three distinct points are plotted at random on a Cartesian plane, for which $-1000 \leq x,y\leq 1000$, such that a triangle is formed.

Consider the following two triangles:

It can be verified that triangle $ABC$ contains the origin, whereas triangle $XYZ$ does not.

Using triangles.txt (right click and ‘Save Link/Target As\dots’), a 27K text file containing the co-ordinates of one thousand “random” triangles, find the number of triangles for which the interior contains the origin.

NOTE: The first two examples in the file represent the triangles in the example given above.

解决方案

设向量$\overrightarrow{a}=(x_1,y_1),\overrightarrow{b}=(x_2,y_2)$。那么向量的叉积为

其中$\theta$为$\overrightarrow{a}$逆时针旋转到$\overrightarrow{b}$的角度。

如果向量$\overrightarrow{b}$的方向为向量$\overrightarrow{a}$逆时针旋转$180°$内,那么$\overrightarrow{a}\times\overrightarrow{b}>0$。

因此,对于$\triangle ABC$任意内一点$P$,如果$\overrightarrow{PA}\times \overrightarrow{PB},\overrightarrow{PB}\times \overrightarrow{PC},\overrightarrow{PC}\times \overrightarrow{PA}$有一个值为$0$,那么$P$在$\triangle ABC$边上。如果三个值的正负性都相同,那么$P$在$\triangle ABC$内部。否则P在$\triangle ABC$外部。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ls = open('p102_triangles.txt', 'r').readlines()


def cross(va: tuple, vb: tuple):
return va[0] * vb[1] - va[1] * vb[0]


def ok(vec_list: list):
u, v, w = cross(vec_list[0], vec_list[1]), cross(vec_list[1], vec_list[2]), cross(vec_list[2], vec_list[0])
if u > 0 and v > 0 and w > 0 or u < 0 and v < 0 and w < 0:
return True
return False


ans = 0
for s in ls:
t = [int(x) for x in s.split(',')]
if ok([(t[0], t[1]), (t[2], t[3]), (t[4], t[5])]):
ans += 1
print(ans)

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
Ujimatsu Chiya 微信 微信
Ujimatsu Chiya 支付宝 支付宝