#184 Triangles containing the origin (難度 75%)
這題題目描述起來很簡單:考慮平面上一些點的集合,這些點滿足:點的座標為整數,以及它們都在一個圓心在原點,半徑為 r 的圓的內部。考慮由這點集當中的點為頂點的三角形,計算圓心 (原點) 在其內部的三角形個數。
對 r=2,一共可以找得到 8 個原點在內部的三角形;r=3 有 360 個,而 r=5 則有 10600 個。試求 r=105 時有多少個。
看起來很簡單,但仔細想下去就會發現很多細節藏在裡面:
- 首先,點的數量很多:用圓面積估計可以得到半徑 105 的圓內整點數約有三萬四千多個,在其中選三個的選法有近七兆種;
- 三角形要包含圓心。說起來簡單,但包含這回事並不容易化成條件;
- 看起來好像有一些對稱性可以用,但這又不是大家都一樣的對稱 (有的翻轉不同,有的翻轉相同等等),要分狀況會很麻煩;
- 等等。
先來提「包含」這件事好了;因為這題其實是個標準的計算幾何題目。所謂計算幾何,以不那麼精準的懶人包說法就是:把幾何問題座標化的解析算式用電腦程式計算的演算法。畢竟電腦要「看」一個幾何圖形只能用描述它的參數性質去看,一些只要圖畫出來對人來說很直接的判斷,電腦程式都需要進行一些運算才能判定;加上一些幾何上的簡單性質其實很容易出現無理數 (以最常見的直角三角形來說好了,畢氏定理求斜邊會有根號,而角度則就連有理數度都是少數),若沒有特別設計的話數值精確度也會是一個問題。
在計算幾何當中要求一個點是否包在簡單多邊形當中,常用的做法有幾個:
- 繞多邊形的邊,每次都看該點是否在邊的同一側:想像沿著多邊形開車,結果繞了一圈都發現目標點都在同一邊,那就可以知道這個點在多邊形裡面了。從這個形象化也很容易知道知道這個方法只對凸多邊形有用,不過三角形一定是凸的所以對三角形也算常用。
- 從點任意發射射線,如果只和多邊形交叉奇數次那就是在裡面:這也是個在圖形上滿直觀的做法。
- 上一個方法的進階版:計算這個多邊形對所求點的卷繞數,如果不是零那就是在裡面。
等等。
單單只運用這些方式就能輕鬆寫程式檢驗題目給的三個數字,但直上 r=105 時就會卡住了。這才是這題的困難點:點集內有 \(O(r^2)\) 個點,所以選三個點組成的三角形個數有 \(O(r^6)\) 個,全部試過一遍的時間會太久。
Continue reading “Project Euler 解題筆記 (4) – #184”