Day20200713—点在三角形内

Day20200713—点在三角形内

前言

因为各种原因,有一段时间没有开始计划性刷题了。在现在看来,无疑是浪费很多时间。

直到某一天,看到一位大牛每天都有计划性地学习,也看到了其中一道非常有趣的题,想起了高中刷题的日子。

所以从今天开始,开始计划性刷题。

关于标题,是因为这一道算法题的重点在于点在三角形内的运用。

参考

题目来源

Point in triangle test

虽然没有使用这个思路,但是非常具有参考价值

题目

描述

在这里插入图片描述

示例

在这里插入图片描述

解题

关键词与细节

不知道动物园的具体位置,动物园在三角形ABC范围内(包括边界与顶点)

3|OA|+2|OB|+|OC|最小,其中点O为动物园

O、A、B、C均为整点,均在同一个平面

条件

点O在三角形内,且满足3|OA|+2|OB|+|OC|最小

这两个条件只保证了点O的3|OA|+2|OB|+|OC|只有一个最小值

但无法保证只有一个点O,因为可能存在多个点O都具有相同的3|OA|+2|OB|+|OC|最小值。

解题思路

条件1

以三角形的三个顶点获取一个正方形区域即可,如下:

在这里插入图片描述

则点O即在正方形区域内,由于O、A、B、C均为整点,数量是有限的。

通过条件1获取点O集合

条件2:点O在三角形区域内

将条件1获取的集合进行筛选,需要满足条件:点O在三角形内

1. 点 O , A , B , C 的 坐 标 分 别 为 : ( x 0 , y 0 ) , ( x 1 , y 1 ) , ( x 2 , y 2 ) , ( x 3 , y 3 ) − − − − − 2. 如 果 点 O 在 三 角 形 A B C 内 的 话 , 会 满 足 以 下 条 件 : S A B O ∗ O C → + S A C O ∗ O B → + S B C O ∗ O A → = 0 → − − − − − 3. 已 知 三 角 形 顶 点 坐 标 , 可 以 通 过 以 下 公 式 计 算 : S A B C = ( 1 / 2 ) ∗ ( x 1 y 2 + x 2 y 3 + x 3 y 1 − x 1 y 3 − x 2 y 1 − x 3 y 2 ) 1.点O,A,B,C的坐标分别为:(x0,y0),(x1,y1),(x2,y2),(x3,y3)\\ -----\\ 2.如果点O在三角形ABC内的话,会满足以下条件:\\ S_{ABO}*\overrightarrow{OC}+S_{ACO}*\overrightarrow{OB}+S_{BCO}*\overrightarrow{OA}=\overrightarrow{0}\\ -----\\ 3.已知三角形顶点坐标,可以通过以下公式计算:\\ S_{ABC}=(1/2)*(x1y2+x2y3+x3y1-x1y3-x2y1-x3y2) 1.O,A,B,C:(x0,y0),(x1,y1),(x2,y2),(x3,y3)2.OABCSABOOC +SACOOB +SBCOOA =0 3.SABC=(1/2)(x1y2+x2y3+x3y1x1y3x2y1x3y2)

条件3:取得最小值

有两个思路

思路1:使用一个标记对象,当出现更小的值时,将产生该值的对象赋予给标记对象

思路2:

使用两个集合,集合1存储所有所有满足条件1和条件2的点O

集合2存储对应产生的3|OA|+2|OB|+|OC|值。获得集合2中最小值的索引,返回集合1对应索引上的值即可


思路1和思路2产生的结果不同,当存在多个点O时,思路2,将返回多个点O,但思路1只能返回一个点O

由于示例返回一个即可,所以使用思路1即可

算法实现

程序代码

import math
class Node(object):
    def __init__(self,x,y):
        self.x = x
        self.y = y
class parrot(object):
    def __init__(self,a,b,c):
        """ a,b,c is a Node """
        self.a = a
        self.b = b
        self.c = c
        self.list_node = [self.a,self.b,self.c]
    def getDist(self,a,b):
        return math.sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))
    def getSum(self,node_o):
        return 3*self.getDist(node_o,self.a)+\
            2*self.getDist(node_o,self.b)+self.getDist(node_o,self.c)
    def areaoftriangle(self,node_a,node_b,node_c):
        #S=(1/2)*(x1y2+x2y3+x3y1-x1y3-x2y1-x3y2)
        """
        node_a.x node_b.x node_c.x
        node_a.y node_b.y node_c.y
        """
        area = (1/2)*abs(
            node_a.x*node_b.y+node_b.x*node_c.y+node_c.x*node_a.y
            \
            -node_a.x*node_c.y-node_b.x*node_a.y-node_c.x*node_b.y
        )
        return area
    def buildvector(self,node_1,node_2):
        return Node(node_2.x-node_1.x,node_2.y-node_1.y)
    def vectorofmultiply(self,k,vector):
        return Node(k*vector.x,k*vector.y)
    def vectorofsum(self,vector1,vector2,vector3):
        return Node(
            vector1.x+vector2.x+vector3.x,vector1.y+vector2.y+vector3.y
        )
    def check_in_out(self,node_o:Node):
        # Node
        vector_oa = self.buildvector(self.a,node_o)
        vector_ob = self.buildvector(self.b,node_o)
        vector_oc = self.buildvector(self.c,node_o)
        # area
        area_aco = self.areaoftriangle(self.a,self.c,node_o)
        area_bco = self.areaoftriangle(self.b,self.c,node_o)
        area_abo = self.areaoftriangle(self.a,self.b,node_o)
        # sum = Sbco*Vector(oa)+Saco*Vector(ob)+Sabo*Vector(oc)=Vector(0,0)
        sum = self.vectorofsum(
            self.vectorofmultiply(area_bco,vector_oa),
            self.vectorofmultiply(area_aco,vector_ob),
            self.vectorofmultiply(area_abo,vector_oc)
        )
        if sum.x == 0 and sum.y == 0:
            return True
        return False
    def run(self):
        list_x,list_y = [],[]
        for i in self.list_node:
            list_x.append(i.x)
            list_y.append(i.y)
        max_x,min_x = max(list_x),min(list_x)
        max_y,min_y = max(list_y),min(list_y)
        result,sumList = [],[]
        minSum = float('inf')
        flag = None
        for i in range(min_x,max_x+1):
            for j in range(min_y,max_y+1):
                if self.check_in_out(Node(i,j)):
                    if minSum > self.getSum(Node(i,j)):
                        minSum = self.getSum(Node(i,j))
                        flag = Node(i,j)
        return flag
if __name__ == "__main__":
    a = Node(0,1)
    b = Node(0,0)
    c = Node(2,0)
    o = Node(1,0)
    parrotObj = parrot(a,b,c)
    flag = parrotObj.run()
    print(flag.x,flag.y)

运行截图

在这里插入图片描述

思考

这一道题,更加侧重于数学思维,例如三角形面积公式,点在三角形内等等知识,都是一个很好的切入点。

三角形面积公式拓展下去,就有很多知识点,例如海伦公式等等。

而点在三角形内,则有重心法等等。

而大多数题都是侧重于经典数据结构和经典的算法。这也验证了当初那句

算法+数据结构=程序

算法和数据结构都同等重要。

后续

将会在这段时间内抽出时间,补充关于点在三角形内的更多方法和证明。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值