Day20200713—点在三角形内
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的坐標分別為:(x0,y0),(x1,y1),(x2,y2),(x3,y3)?????2.如果點O在三角形ABC內的話,會滿足以下條件:SABO?OC→+SACO?OB→+SBCO?OA→=0→?????3.已知三角形頂點坐標,可以通過以下公式計算:SABC=(1/2)?(x1y2+x2y3+x3y1?x1y3?x2y1?x3y2)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.如果點O在三角形ABC內的話,會滿足以下條件:SABO??OC+SACO??OB+SBCO??OA=0?????3.已知三角形頂點坐標,可以通過以下公式計算:SABC?=(1/2)?(x1y2+x2y3+x3y1?x1y3?x2y1?x3y2)
條件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 = xself.y = y class parrot(object):def __init__(self,a,b,c):""" a,b,c is a Node """self.a = aself.b = bself.c = cself.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.xnode_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 areadef 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):# Nodevector_oa = self.buildvector(self.a,node_o)vector_ob = self.buildvector(self.b,node_o)vector_oc = self.buildvector(self.c,node_o)# areaarea_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 Truereturn Falsedef 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 = Nonefor 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)運行截圖
思考
這一道題,更加側重于數學思維,例如三角形面積公式,點在三角形內等等知識,都是一個很好的切入點。
三角形面積公式拓展下去,就有很多知識點,例如海倫公式等等。
而點在三角形內,則有重心法等等。
而大多數題都是側重于經典數據結構和經典的算法。這也驗證了當初那句
算法+數據結構=程序
算法和數據結構都同等重要。
后續
將會在這段時間內抽出時間,補充關于點在三角形內的更多方法和證明。
總結
以上是生活随笔為你收集整理的Day20200713—点在三角形内的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 仙童半导体和“八叛逆”所缔造的硅谷模式
- 下一篇: xilinx debug