若是想要知道怎麼求凸包的直徑
先去學習一下怎麼求解凸包
點這裏去看凸包學習
好了
如今知道了凸包是什麼
咱們很顯然能夠得出,品面內最遠的點對必定在凸包上面(爲啥本身想呀)
而凸包的直徑也就是凸包上最遠點對的距離。優化
繼續,考慮如何求解最遠點對
暴力枚舉?
顯然不必定全部點都會在凸包上,顯然比O(n^2)的枚舉的效率會更加優秀(可是求解凸包還有一個O(nlogn)).net
那麼,有沒有什麼好方法可以求解出最遠點對的距離呢?
先來看一個凸包
code
考慮如何求解距離某一個點最遠的點呢?
咱們轉換一下思路,若是一個點到某一條邊的距離最遠,那麼就能夠推出他到這條邊的兩個端點中的一個必定是最遠的。(本身證實,可能我說錯了。。。。)blog
因此,咱們依次枚舉凸包上的每一條邊
計算一下哪一個點到他的距離最遠,而後計算一下距離
可是,若是就是這樣依次枚舉的話
時間複雜度依舊是O(n^2)
彷佛並無什麼優化get
先給凸包標上點
模板
假設我如今考慮的是AB邊和他距離最遠的點class
很顯然,D點距離他最遠效率
換條邊,換成BC邊
百度
這個時候變成了E點
再繼續?
看看CD邊
這個時候又變成了A點
好了!
咱們如今來看看發生了什麼
咱們的邊依次是: AB->BC->CD
而點依次是:D->E->A
發生了一件很神奇的事情
咱們的邊是逆時針的枚舉
而此時距離他們最遠的點也是逆時針的出現!!
好了
若是本身分析一下
咱們就不可貴出
隨着邊逆時針枚舉,
所對應的點也是逆時針出現的
那麼,這個時候,利用這個性質,
咱們只須要逆時針枚舉邊,而後從上次枚舉到的最遠點繼續逆時針向後枚舉就能求解。
這個時候,O(n^2)被優化到了O(n)
恩,這樣求解就會很快了
因而
來轉一張動圖大體的看一看是怎麼弄的
仍是細節上的小問題
怎麼判斷當前的距離是否更大
最直接的方法,用點到直線的距離公式(本身百度)
另外,還有一種方法
咱們來看看
對於任意一條邊而言
其餘的點離他的距離,就是過這個點作平行線到當前的邊的距離
而邊的長度是固定的,
距離越遠,那麼,邊和點連成的面積也就越大。
還記得上回講凸包的時候,
我寫道:叉積能夠用來求面積
那麼,這裏直接用叉積計算面積便可判斷點是否更遠。
這就是爲啥要單獨介紹一下叉積能夠用來求解面積。
說到這裏差很少了
仍是代碼(核心)
long long GetMax()//求出直徑 { rg long long re=0; if(top==1)//僅有兩個點 return Dis(S[0],S[1]); S[++top]=S[0];//把第一個點放到最後 int j=2; for(int i=0;i<top;++i)//枚舉邊 { while(Cross(S[i],S[i+1],S[j])<Cross(S[i],S[i+1],S[j+1])) j=(j+1)%top; re=max(re,max(Dis(S[i],S[j]),Dis(S[i+1],S[j]))); } return re; }
老樣子,給你一道模板題
戳我
旋轉卡殼的具體實現仍是看一看題目吧~