###### tags: `tutorial` # 計算幾何&其他 by `FHVirus` ---- # 閒聊時間 <iframe width="560" height="315" src="https://www.youtube.com/embed/aLy9rRJ0ApU" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> --- # 大綱 ---- - 暖身題 - 一些基本的運算 - 凸包 - 多邊形面積 - 最遠點對 - 極角排序(Lawfung Sort) - 線段相交 - 座標轉換 - 實作時間/一些不相關的題目 ---- ## 小約定 1. 今天談的東西不是很嚴謹(講者爛)。 2. 沒有特別指名的話都是在討論二維平面上的事。 --- # 暖身 水題大賽? ---- [CF270A](http://codeforces.com/problemset/problem/270/A) ---- [CF1156A](https://codeforces.com/problemset/problem/1156/A) ---- [CF1096C](https://codeforces.com/problemset/problem/1096/C) ---- [CF195D](https://codeforces.com/problemset/problem/195/D) ---- Naïve! --- # 一些基本的運算 ---- 三角形、多邊形、凸多邊形、直角、面積 大家都會吧? ---- ## 向量 以下是不嚴謹的簡單的介紹>< ---- ### 想像成箭頭/座標就對了啦ww <iframe width="560" height="315" src="https://www.youtube.com/embed/fNk_zzaMoSs?start=94" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ---- ### 我們接下來會用到的東西 - 大多是二維向量 - 點積 Dot - 叉積 Cross - 相加相減(Naïve) ---- ### 點積(內積) 大概可以描述兩個向量的方向有多一致。 運算方式:$a \cdot b = a_1 \cdot b_1 + a_2 \cdot b_2 \cdots$ ---- 對於兩個平面的向量: - 若方向相同:$a \cdot b = |a||b|$ - 若兩者垂直:$a \cdot b = 0$ - 若方向相反:$a \cdot b = -|a||b|$ - 一般定義:$a \cdot b = |a||b| \cos \theta$,其中 $\theta$ 為兩向量夾角。 ---- ### [叉積(外積)](https://zh.wikipedia.org/wiki/叉积#/media/File:Cross_product_vector.svg) 常用在計算例舉之類的。 注意到,在二維平面的叉積常常直接取數值, 是因為叉積為三維的向量,且 $a \times b$ 會垂直 $a, b$(垂直平面),運算時多當成數值回傳。 ---- 計算方式: 對於二維的向量而言, $a \times b = a_x \cdot b_y - a_y \cdot b_x$, 注意這會帶正負號。 手算的話也可以以 $a \times b = |a||b| \sin \theta$ 計算。 ---- ### 這可以幹嘛? 判斷兩個向量的夾角! --- # 凸包 Convex Hull 別擔心,這裡沒有 DP 優化。 ---- ## 凸包是啥? > 「凸」的定義是:圖形內任意兩點的連線不會經過圖形外部。 > by [演算法筆記](http://web.ntnu.edu.tw/~algo/ConvexHull.html) 簡單來說,一群點形成的凸包,就是周長最小且包住所有點的殼! ---- ![Convex Hull](http://web.ntnu.edu.tw/~algo/ConvexHull1.png) ---- ## 怎麼做? ---- 掃描、DQ一大堆⋯⋯ 都不是今天要教的! ---- ## Andrew's Monotone Chain! 上下凸包分開找! ---- 對於所有點按一軸排序,邊掃邊做事! ![Andrew's Monotone Chain](http://web.ntnu.edu.tw/~algo/Andrew'sMonotoneChain1.png) ---- ## 要怎麼判斷該不該加點? 還記得叉積嗎? ---- ### 拿前兩點判斷! ---- ### 複雜度 - sort $O(n \log n)$ - 掃描+Stack 操作 均攤 $O(n)$ 總複雜度 $O(n \log n)$! ---- ### [例題:TIOJ 1178 Convex Hull](https://tioj.ck.tp.edu.tw/problems/1178) ---- ### 扣的 ```cpp struct point{ ll x, y; point(){} point(ll x, ll y): x(x), y(y){} // 不會用到加法就不做了 point operator-(point p){ return point(x - p.x, y - p.y); } // Dot Product ll operator*(point p){ return x * p.x + y * p.y; } // Cross Product // 注意運算子優先度! ll operator^(point p){ return x * p.y - y * p.x; } }; ``` ---- ### 扣的 ```cpp // All points, lower convex, upper convex int n; point p[N], lc[N], uc[N]; int lcp, ucp; int32_t main(){ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); cin >> n; FOR(i,n){ int a, b; cin >> a >> b; p[i] = {a, b}; } sort(p, p + n, [](point a, point b){ return a.x < b.x; }); FOR(i,n){ while(ucp > 1 and ((p[i] - uc[ucp - 2]) ^ (uc[ucp - 1] - uc[ucp - 2])) >= 0) --ucp; while(lcp > 1 and ((p[i] - lc[lcp - 2]) ^ (lc[lcp - 1] - lc[lcp - 2])) <= 0) --lcp; uc[ucp++] = p[i]; lc[lcp++] = p[i]; } // 凸包最左最右會重複算到 cout << ucp + lcp - 2 << '\n'; return 0; } ``` ---- 動態凸包什麼的之後再說 ---- ### 習題: - [TIOJ 1371 賢狼之網](https://tioj.ck.tp.edu.tw/problems/1371) --- # 多邊形面積 ---- 大家應該都會算吧? ---- 應該也不少人看過這個: $$ \begin{align} & \frac{1}{2} \begin{vmatrix} x_1 & x_2 & x_3 & \cdots \\ y_1 & y_2 & y_3 & \cdots \end{vmatrix} \\ = & (x_1 \cdot y_2 - y_1 \cdot x_2) + \cdots + (x_n \cdot y_1 - y_n \cdot x_1) \\ = & v_1 \times v_2 + v_2 \times v_3 + \cdots + v_n \times v_1 \end{align} $$ ---- 這東西對於所有多邊形都可以用! 按照逆時針排序點, 順時針的話就取個負號, 複雜度 $O(n)$! ---- ### 就醬,丟題 - [TIOJ 1280 領土 (Territory)](https://tioj.ck.tp.edu.tw/problems/1280) - [TIOJ 1159 房間面積計算](https://tioj.ck.tp.edu.tw/problems/1159) - [Zerojudge d546 剪多邊形](https://zerojudge.tw/ShowProblem?problemid=d546) --- # 最遠點對 ---- 觀察一下不難發現, 最遠點對一定是凸包上的點對! 怎麼做? ---- ### $O(n^2)$? Naïve! ---- ### $O(n)$ ? ---- ### 建凸包+雙指針! 我們沿凸包逆時針進行, 對於遇到的每一個點, 其對應到的最遠點也只會逆時針走! ---- ![Convex Hull](https://lh3.googleusercontent.com/proxy/Ocb2yweIK0ZxBJliWY9P9FOYSr9RNHSP1ZzeiQdH8Qk87mqXN0Vqkka5ZlW31_26m99bVGmKEj-UnVTAfTah8f_RuuBiEiQyRYO07GA_MgkxoPetAA) ---- ### 習題 - [TIOJ 1105 PS3](https://tioj.ck.tp.edu.tw/problems/1105) - 給定 $n$ 個點,求其所形成的最大三角形面積($n \leq 1500$) --- # 極角排序&Lawfung Sort ---- [例題:TIOJ 1205 直角三角形](https://tioj.ck.tp.edu.tw/problems/1205) ---- ### $O(n^3)$ ? Naïve! ---- ### $O(n^2 \log n)$ ? ---- ### 枚舉每一個點,可以做什麼? ---- ### 看他是不是直角那個點! ---- 枚舉每個點當直角, 其他的點按照極角排序好, 雙指針掃過去! (極角:從 x 軸開始逆時針走的夾角) ---- ### 怎麼照極角排序? 還記得內外積嗎? ---- [Lawfung Sort](http://alltherightcodes.blogspot.com/2016/08/tioj-1205.html) ---- ### 小優化 by `warner1129` 把第三、四象限的點以原點對稱過去! ---- ### 習題 - [AtCoder ABC 139F](https://atcoder.jp/contests/abc139/tasks/abc139_f) --- # 線段相交 應該是本課最難搞的東西 ---- 給你平面上四個點 $A, B, C, D$, 求 $\overline{AB}$ 與 $\overline{CD}$ 有沒有相交? ---- ### 重點 - 有沒有漏 case ? - 好好判共線 ---- 想想看? ---- ![Segment intersection](http://web.ntnu.edu.tw/~algo/Intersection3.png) ---- [例題:TIOJ 1876 回家](https://tioj.ck.tp.edu.tw/problems/1876) ---- 怎麼判斷一個點在不在簡單多邊形內部? ---- 一個點隨便取一條射線, 若射線交簡單多邊形於奇數個點, 則在多邊形內! ---- [例題:TIOJ 1423 直線線段相交問題 (Intersection)](w) ---- 怎麼做? ---- 亂做! 不要中毒! --- # 座標轉換 很重要 ---- 例題:[IOI 2007 Pairs](https://tioj.ck.tp.edu.tw/problems/1345) 不要被 IOI 嚇到啦w 這題不難? ---- ### 一維? 還算簡單吧? ---- ### 二維? - 枚舉每一對 - TLE ---- 從頭想,觀察一下! 提示:平面距離有分三種。 對於兩個點 $i, j$,他們的距離: - 歐幾里德:$\sqrt{(x_i - x_j)^2 + (y_i - y_j)^2}$ - 曼哈頓(計程車幾何):$|x_i - x_j| + |y_i - y_j|$ - 切比雪夫:$\max(|x_i - x_j|, |y_i - y_j|)$ ---- 可以發現,如果題目要求的是切比雪夫的話,就可以用區間資料結構掃過去! 但是,要怎麼做? ---- ![](https://i.imgur.com/7f6FpAg.jpg) ---- 展開過程, 如果你上課的時候還看到這邊, 代表 `FHVirus` 沒做完講義, 她會負責現場導一次的。 ---- 這個技巧在二維可以把曼哈頓轉成切比雪夫! ---- 三維也用一樣的技巧, 只不過你的式子會有四個維度! ---- ### $\color{green}{AC}$ 恭喜你會一題 IOI 囉! ---- ### [為什麼很重要?](https://nhspc.csie.ntnu.edu.tw/wp-content/uploads/2020/11/109學年度資訊學科能力競賽決賽試題.pdf) --- # 實作時間/雜題大戰 ---- [ARC113 D](https://atcoder.jp/contests/arc113/tasks/arc113_d) ----
{"metaMigratedAt":"2023-06-15T20:09:43.378Z","metaMigratedFrom":"Content","title":"計算幾何&其他","breaks":true,"contributors":"[{\"id\":\"04d32f9a-57cc-45cd-8549-086ea8ee6d8a\",\"add\":6572,\"del\":213}]"}
    1256 views