導航:首頁 > 源碼編譯 > 凸包演算法graham

凸包演算法graham

發布時間:2023-01-16 22:22:39

『壹』 凸包的平面求法

這個演算法是由數學大師葛立恆(Graham)發明的,他曾經是美國數學學會(AMS)主席、AT&T首席科學家以及國際雜技師協會(IJA)主席。
問題
給定平面上的二維點集,求解其凸包。
過程
⒈ 在所有點中選取y坐標最小的一點H,當作基點。如果存在多個點的y坐標都為最小值,則選取x坐標最小的一點。坐標相同的點應排除。然後按照其它各點p和基點構成的向量<H,p>;與x軸的夾角進行排序,夾角由大至小進行順時針掃描,反之則進行逆時針掃描。實現中無需求得夾角,只需根據餘弦定理求出向量夾角的餘弦值即可。以下圖為例,基點為H,根據夾角由小至大排序後依次為H,K,C,D,L,F,G,E,I,B,A,J。下面進行逆時針掃描。

⒉ 線段<H,K>;一定在凸包上,接著加入C。假設線段<K,C>;也在凸包上,因為就H,K,C三點而言,它們的凸包就是由此三點所組成。但是接下來加入D時會發現,線段<K,D>;才會在凸包上,所以將線段<K,C>;排除,C點不可能是凸包。
⒊ 即當加入一點時,必須考慮到前面的線段是否會出現在凸包上。從基點開始,凸包上每條相臨的線段的旋轉方向應該一致,並與掃描的方向相反。如果發現新加的點使得新線段與上線段的旋轉方向發生變化,則可判定上一點必然不在凸包上。實現時可用向量叉積進行判斷,設新加入的點為pn + 1,上一點為pn,再上一點為pn - 1。順時針掃描時,如果向量<pn - 1,pn>;與<pn,pn + 1>;的叉積為正(逆時針掃描判斷是否為負),則將上一點刪除。刪除過程需要回溯,將之前所有叉積符號相反的點都刪除,然後將新點加入凸包。
在上圖中,加入K點時,由於線段<H,C>要旋轉到<H,K>的角度,為順時針旋轉,所以C點不在凸包上,應該刪除,保留K點。接著加入D點,由於線段<K,D>要旋轉到<H,K>的角度,為逆時針旋轉,故D點保留。按照上述步驟進行掃描,直到點集中所有的點都遍歷完成,即得到凸包。
復雜度
這個演算法可以直接在原數據上進行運算,因此空間復雜度為O⑴。但如果將凸包的結果存儲到另一數組中,則可能在代碼級別進行優化。由於在掃描凸包前要進行排序,因此時間復雜度至少為快速排序的O(nlgn)。後面的掃描過程復雜度為O(n),因此整個演算法的復雜度為O(nlgn)。 對於一個有三個或以上點的點集Q,過程如下:
計算點集最右邊的點為凸包的頂點的起點,如上圖的P3點。
Do
For i = 0 To 總頂點數
計算有向向量P3->Pi
If 其餘頂點全部在有向向量P3->Pi的左側或右側,則Pi點為凸包的下一頂點
Pi點加入凸包列表
GoTo 1
End If
Next
Exit Do
1:
Loop
此過程執行後,點按極角自動順時針或逆時針排序,只需要按任意兩點的次序就可以了。而左側或右側的判斷可以用前述的矢量點積性質實現。 constpi=3.1415926575;zero=1e-6;maxn=1000;maxnum=100000000;varans,temp:extended;n,tot:longint;x,y:array[0..maxn]ofextended;zz,num:array[0..maxn]oflongint;procereswap(varii,jj:extended);vart:extended;begint:=ii;ii:=jj;jj:=t;end;procereinit;vari,j:longint;beginreadln(n);fori:=1tondoreadln(x[i],y[i]);end;functionok(x,midx,y,midy:extended):longint;beginifabs(x-midx)<=zerothenbeginifabs(midy-y)<=zerothenexit(0);ifmidy>ythenexit(1)elseexit(2);endelsebeginifx<midxthenexit(1)elseexit(2);end;end;procereqsort(head,tail:longint);vari,j:longint;midx,midy:extended;begini:=head;j:=tail;midx:=x[(head+tail)div2];midy:=y[(head+tail)div2];repeatwhileok(x[i],midx,y[i],midy)=1doinc(i);whileok(x[j],midx,y[j],midy)=2dodec(j);ifi<=jthenbeginswap(x[i],x[j]);swap(y[i],y[j]);inc(i);dec(j);end;untili>j;ifi<tailthenqsort(i,tail);ifj>headthenqsort(head,j);end;functionPlot(x1,y1,x2,y2:extended):extended;beginPlot:=x1*y2-x2*y1;end;functioncheck(first,last,new:longint):boolean;varax,ay,bx,by:extended;Pt:extended;beginax:=x[last]-x[first];ay:=y[last]-y[first];bx:=x[new]-x[first];by:=y[new]-y[first];ifPlot(ax,ay,bx,by)<=0thenexit(true)elseexit(false);end;procereTbao;vari,j,tail:longint;begintot:=0;zz[1]:=1;tail:=1;fori:=2tondobeginwhile(zz[tail]<>1)andcheck(zz[tail-1],zz[tail],i)dodec(tail);inc(tail);zz[tail]:=i;end;inc(tot,tail-1);fori:=1totail-1donum[i]:=zz[i];zz[1]:=n;tail:=1;fori:=n-1downto1dobeginwhile(zz[tail]<>n)andcheck(zz[tail-1],zz[tail],i)dodec(tail);inc(tail);zz[tail]:=i;end;fori:=1totail-1donum[tot+i]:=zz[i];inc(tot,tail-1);end;functiondist(a,b:longint):extended;begindist:=sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));end;proceremain;vari,j:longint;beginqsort(1,n);Tbao;ans:=0;fori:=1totot-1doans:=ans+dist(num[i],num[i+1]);ans:=ans+dist(num[tot],num[1]);ans:=ans+temp*pi*2;writeln(ans:0:1);end;begininit;main;end.

『貳』 計算機演算法的演算法與程序

雖然演算法與計算機程序密切相關,但二者也存在區別:計算機程序是演算法的一個實例,是將演算法通過某種計算機語言表達出來的具體形式;同一個演算法可以用任何一種計算機語言來表達。
演算法列表
圖論
路徑問題
0/1邊權最短路徑
BFS
非負邊權最短路徑(Dijkstra)
可以用Dijkstra解決問題的特徵
負邊權最短路徑
Bellman-Ford
Bellman-Ford的Yen-氏優化
差分約束系統
Floyd
廣義路徑問題
傳遞閉包
極小極大距離 / 極大極小距離
Euler Path / Tour
圈套圈演算法
混合圖的 Euler Path / Tour
Hamilton Path / Tour
特殊圖的Hamilton Path / Tour 構造
生成樹問題
最小生成樹
第k小生成樹
最優比率生成樹
0/1分數規劃
度限制生成樹
連通性問題
強大的DFS演算法
無向圖連通性
割點
割邊
二連通分支
有向圖連通性
強連通分支
2-SAT
最小點基
有向無環圖
拓撲排序
有向無環圖與動態規劃的關系
二分圖匹配問題
一般圖問題與二分圖問題的轉換思路
最大匹配
有向圖的最小路徑覆蓋
0 / 1矩陣的最小覆蓋
完備匹配
最優匹配
穩定婚姻
網路流問題
網路流模型的簡單特徵和與線性規劃的關系
最大流最小割定理
最大流問題
有上下界的最大流問題
循環流
最小費用最大流 / 最大費用最大流
弦圖的性質和判定
組合數學
解決組合數學問題時常用的思想
逼近
遞推/動態規劃
概率問題
Polya定理
計算幾何 / 解析幾何
計算幾何的核心:叉積 / 面積
解析幾何的主力:復數
基本形

直線,線段
多邊形
凸多邊形 / 凸包
凸包演算法的引進,卷包裹法
Graham掃描法
水平序的引進,共線凸包的補丁
完美凸包演算法
相關判定
兩直線相交
兩線段相交
點在任意多邊形內的判定
點在凸多邊形內的判定
經典問題
最小外接圓
近似O(n)的最小外接圓演算法
點集直徑
旋轉卡殼,對踵點
多邊形的三角剖分
數學/數論
最大公約數
Euclid演算法
擴展的Euclid演算法
同餘方程 / 二元一次不定方程
同餘方程組
線性方程組
高斯消元法
解mod 2域上的線性方程組
整系數方程組的精確解法
矩陣
行列式的計算
利用矩陣乘法快速計算遞推關系
分數
分數樹
連分數逼近
數論計算
求N的約數個數
求phi(N)
求約數和
快速數論變換
……
素數問題
概率判素演算法
概率因子分解
數據結構
組織結構
二叉堆
左偏樹
二項樹
勝者樹
跳躍表
樣式圖標
斜堆
reap
統計結構
樹狀數組
虛二叉樹
線段樹
矩形面積並
圓形面積並
關系結構
Hash表
並查集
路徑壓縮思想的應用
STL中的數據結構
vector
deque
set / map
動態規劃/記憶化搜索
動態規劃和記憶化搜索在思考方式上的區別
最長子序列系列問題
最長不下降子序列
最長公共子序列
一類NP問題的動態規劃解法
樹型動態規劃
背包問題
動態規劃的優化
四邊形不等式
函數的凸凹性
狀態設計
規劃方向
線性規劃
常用思想
二分
最小表示法

KMP
Trie結構
後綴樹/後綴數組
LCA/RMQ
有限狀態自動機理論
排序
選擇/冒泡
快速排序
堆排序
歸並排序
基數排序
拓撲排序
排序網路

『叄』 我是用的是C語言,想在黑龍江省ACM大賽中拿三等獎,應該掌握那些演算法……

當中有幾百種計算機常用的演算法的框架和模板,如果你還在為演算法問題而困擾時,這資料會讓你廓然開朗,我也在學,很有用所以極力推薦給你.

框架部分目錄如下:

圖論

路徑問題

0/1邊權最短路徑

BFS

非負邊權最短路徑(Dijkstra)

可以用Dijkstra解決問題的特徵

負邊權最短路徑

Bellman-Ford

Bellman-Ford的Yen-氏優化

差分約束系統

Floyd

廣義路徑問題

傳遞閉包

極小極大距離/極大極小距離

EulerPath/Tour

圈套圈演算法

混合圖的EulerPath/Tour

HamiltonPath/Tour

特殊圖的HamiltonPath/Tour構造

生成樹問題

最小生成樹

第k小生成樹

最優比率生成樹

0/1分數規劃

度限制生成樹

連通性問題

強大的DFS演算法

無向圖連通性

割點

割邊

二連通分支

有向圖連通性

強連通分支

2-SAT

最小點基

有向無環圖

拓撲排序

有向無環圖與動態規劃的關系

二分圖匹配問題

一般圖問題與二分圖問題的轉換思路

最大匹配(OK)

有向圖的最小路徑覆蓋

0/1矩陣的最小覆蓋

完備匹配(OK)

最優匹配(OK)

穩定婚姻

網路流問題

網路流模型的簡單特徵和與線性規劃的關系

最大流最小割定理

最大流問題(OK)

有上下界的最大流問題

循環流

最小費用最大流/最大費用最大流

弦圖的性質和判定


組合數學

解決組合數學問題時常用的思想

逼近

遞推/動態規劃

概率問題

Polya定理


計算幾何/解析幾何

計算幾何的核心:叉積/面積

解析幾何的主力:復數

基本形

直線,線段

多邊形

凸多邊形/凸包

凸包演算法的引進,卷包裹法

Graham掃描法

水平序的引進,共線凸包的補丁

完美凸包演算法

相關判定

兩直線相交

兩線段相交

點在任意多邊形內的判定

點在凸多邊形內的判定

經典問題

最小外接圓

近似O(n)的最小外接圓演算法

點集直徑

旋轉卡殼,對踵點

多邊形的三角剖分


數學/數論

高精度計算

高數度加減法、乘除法

最大公約數

Euclid演算法

擴展的Euclid演算法

同餘方程/二元一次不定方程

同餘方程組

線性方程組

高斯消元法

解mod2域上的線性方程組

整系數方程組的精確解法

矩陣

行列式的計算

利用矩陣乘法快速計算遞推關系

分數

分數樹

連分數逼近

數論計算

求N的約數個數

求phi(N)

求約數和

快速數論變換

……

素數問題

概率判素演算法

概率因子分解


數據結構

組織結構

二叉堆

左偏樹

二項樹

勝者樹

跳躍表

樣式圖標

斜堆

reap

統計結構

樹狀數組

虛二叉樹

線段樹

矩形面積並

圓形面積並

關系結構

Hash表

並查集

路徑壓縮思想的應用

STL中的數據結構

vector

deque

set/map


動態規劃/記憶化搜索

動態規劃和記憶化搜索在思考方式上的區別

最長子序列系列問題

最長不下降子序列

最長公共子序列

一類NP問題的動態規劃解法

樹型動態規劃

背包問題

動態規劃的優化

四邊形不等式

函數的凸凹性

狀態設計

規劃方向


線性規劃

常用思想

二分

最小表示法

KMP

Trie結構

後綴樹/後綴數組

LCA/RMQ

有限狀態自動機理論

排序

選擇/冒泡

快速排序

堆排序

歸並排序(OK)

基數排序

拓撲排序

排序網路


『肆』 西南交大acm動態規劃問題有哪些

ACM常用演算法及練習
第一階段:練經典常用演算法,下面的每個演算法給我打上十到二十遍,同時自己精簡代碼,
因為太常用,所以要練到寫時不用想,10-15分鍾內打完,甚至關掉顯示器都可以把程序打
出來.
1.最短路(Floyd、Dijstra,BellmanFord)
2.最小生成樹(先寫個prim,kruscal要用並查集,不好寫)
3.大數(高精度)加減乘除
4.二分查找. (代碼可在五行以內)
5.叉乘、判線段相交、然後寫個凸包.
6.BFS、DFS,同時熟練hash表(要熟,要靈活,代碼要簡)
7.數學上的有:輾轉相除(兩行內),線段交點、多角形面積公式.
8. 調用系統的qsort, 技巧很多,慢慢掌握.
9. 任意進制間的轉換

第二階段:練習復雜一點,但也較常用的演算法。
如:
1. 二分圖匹配(匈牙利),最小路徑覆蓋
2. 網路流,最小費用流。
3. 線段樹.
4. 並查集。
5. 熟悉動態規劃的各個典型:LCS、最長遞增子串、三角剖分、記憶化dp
6.博弈類演算法。博弈樹,二進製法等。
7.最大團,最大獨立集。
8.判斷點在多邊形內。
9. 差分約束系統.
10. 雙向廣度搜索、A*演算法,最小耗散優先.

相關的知識

圖論

路徑問題
0/1邊權最短路徑
BFS
非負邊權最短路徑(Dijkstra)
可以用Dijkstra解決問題的特徵
負邊權最短路徑
Bellman-Ford
Bellman-Ford的Yen-氏優化
差分約束系統
Floyd
廣義路徑問題
傳遞閉包
極小極大距離 / 極大極小距離
Euler Path / Tour
圈套圈演算法
混合圖的 Euler Path / Tour
Hamilton Path / Tour
特殊圖的Hamilton Path / Tour 構造

生成樹問題
最小生成樹
第k小生成樹
最優比率生成樹
0/1分數規劃
度限制生成樹

連通性問題
強大的DFS演算法
無向圖連通性
割點
割邊
二連通分支
有向圖連通性
強連通分支
2-SAT
最小點基

有向無環圖
拓撲排序
有向無環圖與動態規劃的關系

二分圖匹配問題
一般圖問題與二分圖問題的轉換思路
最大匹配
有向圖的最小路徑覆蓋
0 / 1矩陣的最小覆蓋
完備匹配
最優匹配
穩定婚姻

網路流問題
網路流模型的簡單特徵和與線性規劃的關系
最大流最小割定理
最大流問題
有上下界的最大流問題
循環流
最小費用最大流 / 最大費用最大流

弦圖的性質和判定

組合數學

解決組合數學問題時常用的思想
逼近
遞推 / 動態規劃
概率問題
Polya定理

計算幾何 / 解析幾何

計算幾何的核心:叉積 / 面積
解析幾何的主力:復數

基本形

直線,線段
多邊形

凸多邊形 / 凸包
凸包演算法的引進,卷包裹法

Graham掃描法
水平序的引進,共線凸包的補丁

完美凸包演算法

相關判定
兩直線相交
兩線段相交
點在任意多邊形內的判定
點在凸多邊形內的判定

經典問題
最小外接圓
近似O(n)的最小外接圓演算法
點集直徑
旋轉卡殼,對踵點
多邊形的三角剖分

數學 / 數論

最大公約數
Euclid演算法
擴展的Euclid演算法
同餘方程 / 二元一次不定方程
同餘方程組

線性方程組
高斯消元法
解mod 2域上的線性方程組
整系數方程組的精確解法

矩陣
行列式的計算
利用矩陣乘法快速計算遞推關系

分數
分數樹
連分數逼近

數論計算
求N的約數個數
求phi(N)
求約數和
快速數論變換
……

素數問題
概率判素演算法
概率因子分解

數據結構

組織結構
二叉堆
左偏樹
二項樹
勝者樹
跳躍表
樣式圖標
斜堆
reap

統計結構
樹狀數組
虛二叉樹
線段樹
矩形面積並
圓形面積並

關系結構
Hash表
並查集
路徑壓縮思想的應用

STL中的數據結構
vector
deque
set / map

動態規劃 / 記憶化搜索

動態規劃和記憶化搜索在思考方式上的區別

最長子序列系列問題
最長不下降子序列
最長公共子序列
最長公共不下降子序列

一類NP問題的動態規劃解法

樹型動態規劃

背包問題

動態規劃的優化
四邊形不等式
函數的凸凹性
狀態設計
規劃方向

線性規劃

常用思想

二分 最小表示法



KMP Trie結構
後綴樹/後綴數組 LCA/RMQ
有限狀態自動機理論

排序
選擇/冒泡 快速排序 堆排序 歸並排序
基數排序 拓撲排序 排序網路

中級:
一.基本演算法:
(1)C++的標准模版庫的應用. (poj3096,poj3007)
(2)較為復雜的模擬題的訓練(poj3393,poj1472,poj3371,poj1027,poj2706)
二.圖演算法:
(1)差分約束系統的建立和求解. (poj1201,poj2983)
(2)最小費用最大流(poj2516,poj2516,poj2195)
(3)雙連通分量(poj2942)
(4)強連通分支及其縮點.(poj2186)
(5)圖的割邊和割點(poj3352)
(6)最小割模型、網路流規約(poj3308, )
三.數據結構.
(1)線段樹. (poj2528,poj2828,poj2777,poj2886,poj2750)
(2)靜態二叉檢索樹. (poj2482,poj2352)
(3)樹狀樹組(poj1195,poj3321)
(4)RMQ. (poj3264,poj3368)
(5)並查集的高級應用. (poj1703,2492)
(6)KMP演算法. (poj1961,poj2406)
四.搜索
(1)最優化剪枝和可行性剪枝
(2)搜索的技巧和優化 (poj3411,poj1724)
(3)記憶化搜索(poj3373,poj1691)

五.動態規劃
(1)較為復雜的動態規劃(如動態規劃解特別的施行商問題等)
(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)
(2)記錄狀態的動態規劃. (POJ3254,poj2411,poj1185)
(3)樹型動態規劃(poj2057,poj1947,poj2486,poj3140)
六.數學
(1)組合數學:
1.容斥原理.
2.抽屜原理.
3.置換群與Polya定理(poj1286,poj2409,poj3270,poj1026).
4.遞推關系和母函數.

(2)數學.
1.高斯消元法(poj2947,poj1487, poj2065,poj1166,poj1222)
2.概率問題. (poj3071,poj3440)
3.GCD、擴展的歐幾里德(中國剩餘定理) (poj3101)
(3)計算方法.
1.0/1分數規劃. (poj2976)
2.三分法求解單峰(單谷)的極值.
3.矩陣法(poj3150,poj3422,poj3070)
4.迭代逼近(poj3301)
(4)隨機化演算法(poj3318,poj2454)
(5)雜題.
(poj1870,poj3296,poj3286,poj1095)
七.計算幾何學.
(1)坐標離散化.
(2)掃描線演算法(例如求矩形的面積和周長並,常和線段樹或堆一起使用).
(poj1765,poj1177,poj1151,poj3277,poj2280,poj3004)
(3)多邊形的內核(半平面交)(poj3130,poj3335)
(4)幾何工具的綜合應用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)

高級:
一.基本演算法要求:
(1)代碼快速寫成,精簡但不失風格
(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)
(2)保證正確性和高效性. poj3434
二.圖演算法:
(1)度限制最小生成樹和第K最短路. (poj1639)
(2)最短路,最小生成樹,二分圖,最大流問題的相關理論(主要是模型建立和求解)
(poj3155, poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446
(3)最優比率生成樹. (poj2728)
(4)最小樹形圖(poj3164)
(5)次小生成樹.
(6)無向圖、有向圖的最小環
三.數據結構.
(1)trie圖的建立和應用. (poj2778)
(2)LCA和RMQ問題(LCA(最近公共祖先問題) 有離線演算法(並查集+dfs) 和 在線演算法
(RMQ+dfs)).(poj1330)
(3)雙端隊列和它的應用(維護一個單調的隊列,常常在動態規劃中起到優化狀態轉移的
目的). (poj2823)
(4)左偏樹(可合並堆).
(5)後綴樹(非常有用的數據結構,也是賽區考題的熱點).
(poj3415,poj3294)
四.搜索
(1)較麻煩的搜索題目訓練(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)
(2)廣搜的狀態優化:利用M進制數存儲狀態、轉化為串用hash表判重、按位壓縮存儲狀態、雙向廣搜、A*演算法. (poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)
(3)深搜的優化:盡量用位運算、一定要加剪枝、函數參數盡可能少、層數不易過大、可以考慮雙向搜索或者是輪換搜索、IDA*演算法. (poj3131,poj2870,poj2286)
五.動態規劃
(1)需要用數據結構優化的動態規劃.
(poj2754,poj3378,poj3017)
(2)四邊形不等式理論.
(3)較難的狀態DP(poj3133)
六.數學
(1)組合數學.
1.MoBius反演(poj2888,poj2154)
2.偏序關系理論.
(2)博奕論.
1.極大極小過程(poj3317,poj1085)
2.Nim問題.
七.計算幾何學.
(1)半平面求交(poj3384,poj2540)
(2)可視圖的建立(poj2966)
(3)點集最小圓覆蓋.
(4)對踵點(poj2079)
八.綜合題.
(poj3109,poj1478,poj1462,poj2729,poj2048,poj3336,poj3315,poj2148,poj1263)

初期:
一.基本演算法:
(1)枚舉. (poj1753,poj2965) (2)貪心(poj1328,poj2109,poj2586)
(3)遞歸和分治法. (4)遞推.
(5)構造法.(poj3295) (6)模擬法.(poj1068,poj2632,poj1573,poj2993,poj2996)
二.圖演算法:
(1)圖的深度優先遍歷和廣度優先遍歷.
(2)最短路徑演算法(dijkstra,bellman-ford,floyd,heap+dijkstra)
(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)
(3)最小生成樹演算法(prim,kruskal)
(poj1789,poj2485,poj1258,poj3026)
(4)拓撲排序 (poj1094)
(5)二分圖的最大匹配 (匈牙利演算法) (poj3041,poj3020)
(6)最大流的增廣路演算法(KM演算法). (poj1459,poj3436)
三.數據結構.
(1)串 (poj1035,poj3080,poj1936)
(2)排序(快排、歸並排(與逆序數有關)、堆排) (poj2388,poj2299)
(3)簡單並查集的應用.
(4)哈希表和二分查找等高效查找法(數的Hash,串的Hash)
(poj3349,poj3274,POJ2151,poj1840,poj2002,poj2503)
(5)哈夫曼樹(poj3253)
(6)堆
(7)trie樹(靜態建樹、動態建樹) (poj2513)
四.簡單搜索
(1)深度優先搜索 (poj2488,poj3083,poj3009,poj1321,poj2251)
(2)廣度優先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)
(3)簡單搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)
五.動態規劃
(1)背包問題. (poj1837,poj1276)
(2)型如下表的簡單DP(可參考lrj的書 page149):
1.E[j]=opt (poj3267,poj1836,poj1260,poj2533)
2.E[i,j]=opt (最長公共子序列)
(poj3176,poj1080,poj1159)
3.C[i,j]=w[i,j]+opt.(最優二分檢索樹問題)
六.數學
(1)組合數學:
1.加法原理和乘法原理.
2.排列組合.
3.遞推關系.
(POJ3252,poj1850,poj1019,poj1942)
(2)數論.
1.素數與整除問題
2.進制位.
3.同餘模運算.
(poj2635, poj3292,poj1845,poj2115)
(3)計算方法.
1.二分法求解單調函數相關知識.(poj3273,poj3258,poj1905,poj3122)
七.計算幾何學.
(1)幾何公式.
(2)叉積和點積的運用(如線段相交的判定,點到線段的距離等). (poj2031,poj1039)
(3)多邊型的簡單演算法(求面積)和相關判定(點在多邊型內,多邊型是否相交)
(poj1408,poj1584)
(4)凸包. (poj2187,poj1113)

『伍』 求大神詳細講解c/c++/pascal凸包演算法

實這個演算法是在一年前得某場比賽中臨時抱佛腳學的,今天重新的來溫習了一遍
如何來理解凸包?一組平面上的點,求一個包含所有點的最小的凸多邊形,這就是凸包問題了。這可以形象地想成這樣:在地上放置一些不可移動的木樁,用一根繩子把他們盡量緊地圈起來,這就是凸包了,網路中的這張圖很生動+活潑+形象,所以你懂的

好說完這個我們首先要來了解下極角排序和左轉判定
極角排序:就是選取一個最左的點,按y最小,其次x最小來定義,接下來所有的點針對該點的射線,
按角度由小到大,若相同按距離由近到遠來排序
左轉判定:這個和叉積有關,對於向量p1(x1,y1),p2(x2,y2)如果x1*y2-x2*y1>0,則從p1到p2左轉

我學的是Graham演算法,那麼接下來來介紹下該演算法
(1)選取最下左的點P0
(2)計算出每個點相對於P0的角度和距離(利用這個來排序)排序
(3)設點數為n,將p[n-1]和p[0]入棧,判斷點集合是否為一條直線(初始k=2表示當前凸包的大小)
(4)i從1到n-1遍歷,對於p[k-1],p[k-2],p[i]若滿足左轉,將p[i]壓入棧
否則i--,k--
(5)k--,返回k表示凸包的點數

下面是我寫的模板

int Polygon::Graham(Polygon &con){//別用自己做對象
int t=0,i;
Point tmp;
//先y最小再x最小
for(i=1;i<n;i++)if(p[i]<p[t])t=i;
swap(p[t],p[0]);
for(i=0;i<n;i++){
tmp=p[i]-p[0];
p[i].dis=tmp.Len2();
p[i].angle=atan2(tmp.y,tmp.x);
}
sort(p,p+n,_cmp);
//for(int i=0;i<n;i++)p[i].out();
//cout<<"***"<<endl;
int k=0;
con.p[k++]=p[n-1];
con.p[k++]=p[0];
if(Sig(p[1].angle-p[n-1].angle)==0)con.p[k++]=p[n-1];//凸包為一線段
else{
for(i=1;i<n;i++){
//con[k-1].out();
//con[k-2].out();
//p[i].out();
if(Sig(Cross(con.p[k-1],con.p[k-2],p[i]))>0)con.p[k++]=p[i];
else {i--;k--;}
//cout<<"---"<<endl;
//for(int j=0;j<k;j++)con[j].out();
//system("pause");
}
}
return con.n=--k;
}
/*
9
1 4
3 6
5 7
2 2
3 3
5 4
8 3
9 6
7 1
*/

摘自http://blog.csdn.net/foreverlin1204/article/details/6221986

『陸』 請問凸包演算法的時間復雜度的測試代碼怎麼寫

代碼一
(在編輯器中將"_ "(下劃線+空格)替換成兩個空格即可編譯; 注意要去掉開通的雙位元組中文空格,蛋疼的網路。)
#include <iostream>
#include <algorithm>
using namespace std;
struct point
{
_ _ int x;
_ _ int y;
} p[30005],res[30005];//p標記圖中所有的點,res標記凸包上的點
int cmp(point p1,point p2)
{
_ _ return p1.y < p2.y || (p1.y == p2.y && p1.x < p2.x);
}
bool ral(point p1,point p2,point p3) //用叉乘判斷點的位置
{
_ _ return (p2.x - p1.x)*(p3.y - p1.y) > (p3.x - p1.x)*(p2.y - p1.y);
}
int main()
{
_ _ int n,i;
_ _ while(scanf("%d",&n) != EOF) //一共有n個點
_ _ {
_ _ _ _ for(i = 0; i < n; i++)
_ _ _ _ _ _ scanf("%d%d",&p[i].x,&p[i].y);
__ _ _ if(n == 1)
_ _ _ _ {
_ _ _ _ _ _ printf("%d %d\n",p[0].x,p[0].y);
_ _ _ _ _ _ continue;
_ _ _ _ }
_ _ _ _ if(n == 2)
_ _ _ _ {
_ _ _ _ _ _ printf("%d %d\n",p[0].x,p[0].y);
_ _ _ _ _ _ printf("%d %d\n",p[1].x,p[1].y);
_ _ _ _ _ _ continue;
_ _ _ _ }
_ _ _ _ sort(p,p + n,cmp);
_ _ _ _ res[0] = p[0];
_ _ _ _ res[1] = p[1];
_ _ _ _ int top = 1;
_ _ _ _ for(i = 2; i < n; i++)
_ _ _ _ {
_ _ _ _ _ _ while(top && !ral(res[top],res[top - 1],p[i]))
_ _ _ _ _ _ top--;
_ _ _ _ _ _ res[++top] = p[i];
_ _ _ _ }
_ _ _ _ int len = top;
_ _ _ _ res[++top] = p[n - 2];
_ _ _ _ for(i = n - 3; i >= 0; i--)
_ _ _ _ {
_ _ _ _ _ _ while(top != len && !ral(res[top],res[top - 1],p[i]))
_ _ _ _ _ _ top--;
_ _ _ _ _ _ res[++top] = p[i];
_ _ _ _ }
_ _ _ _ for(i = 0; i < top; i++)
_ _ _ _ _ _ printf("%d %d\n",res[i].x,res[i].y);//輸出凸包上的點
_ _ }
_ _ return 0;
}
代碼二
#include <iostream> // 求點集合的凸包的gram演算法。n是頂點個數,x,y是頂點
坐標。
#include <fstream> // order 是按照頂點和左下腳的角度的排序後數組。
#include <deque> // tu即是逆時針的凸包上的頂點。
#include <math.h> //
using namespace std; //使用條件:1。點可以任意給,可重復。
// 2。三個以及以上的點。
ifstream fin("input.txt"); // 3。已經考慮了邊上有點的情況。
#define NN 1000
#define pi 3.1415827
typedef struct Cseg{
double x,y,tg;
}Cseg;
int n;
double x[NN],y[NN];
deque <Cseg> order;
deque <int> tu;
Cseg seg1;
deque <Cseg> ::iterator p1;
deque <int> ::iterator p,q;
void in();
void gram();
void makeorder(int s);
double dist(double x1,double yy1,double x2,double yy2);
double cross(double x1,double yy1,double x2,double yy2);
void out();
int main()
{
in();
gram();
out();
return 0;
}
void out()
{
int i;
for (i=0;i<tu.size();i++){
cout<<order[tu].x<<" "<<order[tu].y<<endl;
}
cout<<tu.size()<<" Edges Polydgon"<<endl;
return;
}
void in()
{
int i;
fin>>n;
for (i=0;i<n;i++)
fin>>x>>y;
return;
}
void gram()
{
int i,mm;
mm=0;
for (i=1;i<n;i++)
if (y[mm]>y+1e-9) mm=i;
else if (fabs(y[mm]-y)<1e-9 && x[mm]>x+1e-9) mm=i;
makeorder(mm);
seg1.x=x[mm];
seg1.y=y[mm];
tu.clear();
tu.push_back(0);
tu.push_back⑴;
tu.push_back⑵;
for (i=3;i<order.size();i++){
p=tu.end();
seg1.x=order.x;
seg1.y=order.y;
p--;
q=p-1;
if
(cross(order[*p].x-order[*q].x,order[*p].y-order[*q].y,order.x-order[*
q].x,order.y-order[*q].y)>1e-9)
tu.push_back(i);
else{
tu.pop_back();
i--;
continue;
//tu.push_back(i);
}
}//for
return;
}
void makeorder(int s)
{
int i;
double tg;
order.clear();
for (i=0;i<n;i++){
if (i==s) continue;
tg=atan2(y-y[s],x-x[s]);
seg1.x=x;
seg1.y=y;
seg1.tg=tg;
p1=order.begin();
while (p1!=order.end()){
if (fabs(tg-p1->tg)<1e-9){
if
(dist(x[s],y[s],x,y)>dist(x[s],y[s],p1->x,p1->y)+1e-9) {
p1->x=x;
p1->y=y;
}
break;
}
else
if (tg<p1->tg){
order.insert(p1,seg1);
break;
}
p1++;
}//while
if (p1==order.end()) order.insert(p1,seg1);
}//for
seg1.x=x[s];seg1.y=y[s];
order.insert(order.begin(),seg1);
//for (i=0;i<order.size();i++)
// printf("i=%d %lf %lf
%lf\n",i,order.x,order.y,order.tg*180/pi);
return;
}
double cross(double x1,double yy1,double x2,double yy2)
{
return (x1*yy2-x2*yy1);
}
double dist(double x1,double yy1,double x2,double yy2)
{
return pow((x1-x2)*(x1-x2)+(yy1-yy2)*(yy1-yy2),0.5);
}
代碼三
P標程{pku 1113 }
{$Q-,S-,R-}
const
pi=3.1415926575;
zero=1e-6;
maxn=1000;
maxnum=100000000;
var
ans,temp :extended;
n,tot :longint;
x,y :array[0..maxn]of extended;
zz,num :array[0..maxn]of longint;
procere swap(var ii,jj:extended);
var
t :extended;
begin
t:=ii;ii:=jj;jj:=t;
end;
procere init;
var
i,j :longint;
begin
readln(n,temp);
for i:=1 to n do readln(x[i],y[i]);
end;
function ok(x,midx,y,midy:extended):longint;
begin
if abs(x-midx)<=zero then
begin
if abs(midy-y)<=zero then exit(0);
if midy>y then exit⑴
else exit⑵;
end
else
begin
if x<midx then exit⑴
else exit⑵;
end;
end;
procere qsort(head,tail:longint);
var
i,j :longint;
midx,midy :extended;
begin
i:=head;
j:=tail;
midx:=x[(head+tail) div 2];
midy:=y[(head+tail) div 2];
repeat
while ok(x[i],midx,y[i],midy)=1 do inc(i);
while ok(x[j],midx,y[j],midy)=2 do dec(j);
if i<=j then
begin
swap(x[i],x[j]);
swap(y[i],y[j]);
inc(i);
dec(j);
end;
until i>j;
if i<tail then qsort(i,tail);
if j>head then qsort(head,j);
end;
function Plot(x1,y1,x2,y2:extended):extended;
begin
Plot:=x1*y2-x2*y1;
end;
function check(first,last,new:longint):boolean;
var
ax,ay,bx,by :extended;
Pt :extended;
begin
ax:=x[last]-x[first];ay:=y[last]-y[first];
bx:=x[new]-x[first];by:=y[new]-y[first];
if Plot(ax,ay,bx,by)<-zero then exit(true)
else exit(false);
end;
procere Tbao;
var
i,j,tail :longint;
begin
tot:=0;
zz[1]:=1;tail:=1;
for i:=2 to n do
begin
while (zz[tail]<>1)and check(zz[tail-1],zz[tail],i) do dec(tail);
inc(tail);
zz[tail]:=i;
end;
inc(tot,tail-1);
for i:=1 to tail-1 do
num[i]:=zz[i];
zz[1]:=n;tail:=1;
for i:=n-1 downto 1 do
begin
while (zz[tail]<>n)and check(zz[tail-1],zz[tail],i) do dec(tail);
inc(tail);
zz[tail]:=i;
end;
for i:=1 to tail-1 do
num[tot+i]:=zz[i];
inc(tot,tail-1);
end;
function dist(a,b:longint):extended;
begin
dist:=sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
end;
procere main;
var
i,j :longint;
begin
qsort(1,n);
Tbao;
ans:=0;
for i:=1 to tot-1 do
ans:=ans+dist(num[i],num[i+1]);
ans:=ans+dist(num[tot],num[1]);
ans:=ans+temp*pi*2;
writeln(ans:0:0);
end;
begin
init;
main;
end.

『柒』 pascal高維凸包

最簡單的:暴力法= =
然後就有包裹法,加點法,一大堆,你要要就在HI上找我,給你發資料

『捌』 參加ACM大賽應該准備哪些課程

課程:

(1)基本演算法: 二分,分治,貪心

(2) 離散數學離散數學動態規劃

(3) 搜索演算法:深度優先 搜索,廣度優先搜A*演算法 ,阿爾法貝塔剪枝

(4)數據結構:線段樹, 樹狀數組,並查集,Trie圖

(5)圖論問題:最小生成樹 最短路 強連通分量、橋和割點

(6)網路流演算法:基本的網路流演算法,Dinic演算法,帶上下界的網路流,最小費用流

(7)計算幾何:線與線求交,線與面求交,求凸包,半平面求交等

(8) 離散數學,高等數學,線性代數,初等數論,計算幾何

(9)計算機專業英語

(10)C++;基礎的遞歸、枚舉演算法

(8)凸包演算法graham擴展閱讀:

1.參賽隊伍最多由三名參賽隊員組成。

2.競賽中命題10題左右,試題描述為英文,比賽時間為5個小時,前四個小時可以實時看到排名,最後一小時封榜,無法看到排名。

3.競賽可以使用的語言:Java, C, C++, Kotlin 和 Python。

4.重點考察選手的演算法和程序設計能力,不考察實際工程中常用的系統編程,多線程編程等等;

5.選手可攜帶任何非電子類資料,包括書籍和列印出來的程序等,部分賽區會對選手攜帶的紙質資料做限制。

6.評委負責將結果(正確或出錯的類型)通過網路盡快返回給選手,除此之外不提供任何額外幫助;

7.每個題目對應一種顏色的氣球,通過該題目的隊伍會得到對應顏色氣球。每道題目第一支解決掉它的隊還會額外獲得一個「FIRST PROBLEM SOLVED」的氣球。

『玖』 凸包演算法

凸包類型的題演算法主要有三種: JarvisMarch 演算法、 Graham 演算法和 Andrew 演算法,這三種演算法時間性能上遞增。

縱坐標最小然後橫坐標最小的點一定是凸包上的點, 我們將其記為 ,從 開始,按逆時針的方向,逐個找凸包上的點,每前進一步找到一個點,所以叫作步進法。

把所有點放在二維坐標系中,則縱坐標最小的點一定是凸包上的點,記為 。計算各個點相對 的幅角,按從小到大的順序對各個點排序。(當幅角相同是,距離 比較近的排在前面)則幅角最小的點和最大的點一定在凸包上。取幅角最小的點記為 ,將 、 入棧。連接棧頂的點和次棧頂的點,得到直線 ,看當前點是在直線的右邊還是左邊,在右邊則棧頂元素不是凸包上的點,將其彈出,返回繼續執行。如果在左邊,則當前點是凸包上的點。一直到幅角最大的那個點為之。

預處理排序改為水平排序,按照橫坐標從小到大進行排序,橫坐標相同則按縱坐標從小到大排。按照 graham 演算法思想從 、 掃描所有點得到下凸包,再從 、 掃描所有點得到上凸包,二者結合即為整個凸包。(注意:這里的 不一定在凸包里)

『拾』 凸包的發展歷史,急需,越詳細越好,謝謝!!!!

⒈對於一個集合D,D中任意有限個點的線性組合的全體稱為D的凸包。 ⒉對於一個集合D,所有包含D的凸集之交稱為D的凸包。 可以證明,上述兩種定義是等價的 概念
1 點集Q的凸包(convex hull)是指一個最小凸多邊形,滿足Q中的點或者在多邊形邊上或者在其內。右圖中由紅色線段表示的多邊形就是點集Q={p0,p1,...p12}的凸包。 2 一組平面上的點,求一個包含所有點的最小的凸多邊形,這就是凸包問題了。這可以形象地想成這樣:在地上放置一些不可移動的木樁,用一根繩子把他們盡量緊地圈起來,並且為凸邊形,這就是凸包了。編輯本段平面凸包求法常見求法
2.0 Graham's Scan法求解凸包問題
概念 凸包(Convex Hull)是一個計算幾何(圖形學)中的概念。用不嚴謹的話來講,給定二維平面上的點集,凸包就是將最外層的點連接起來構成的凸多邊型,它能包含點集中所有點的。嚴謹的定義和相關概念參見維基網路:凸包。 這個演算法是由數學大師葛立恆(Graham)發明的,他曾經是美國數學學會(AMS)主席、AT&T首席科學家以及國際雜技師協會(IJA)主席。(太汗了,這位大牛還會玩雜技~) 問題 給定平面上的二維點集,求解其凸包。 過程 ⒈ 在所有點中選取y坐標最小的一點H,當作基點。如果存在多個點的y坐標都為最小值,則選取x坐標最小的一點。坐標相同的點應排除。然後按照其它各點p和基點構成的向量<H,p>;與x軸的夾角進行排序,夾角由大至小進行順時針掃描,反之則進行逆時針掃描。實現中無需求得夾角,只需根據向量的內積公式求出向量的模即可。以下圖為例,基點為H,根據夾角由小至大排序後依次為H,K,C,D,L,F,G,E,I,B,A,J。下面進行逆時針掃描。 ⒉ 線段<H,K>;一定在凸包上,接著加入C。假設線段<K,C>;也在凸包上,因為就H,K,C三點而言,它們的凸包就是由此三點所組成。但是接下來加入D時會發現,線段<K,D>;才會在凸包上,所以將線段<K,C>;排除,C點不可能是凸包。 ⒊ 即當加入一點時,必須考慮到前面的線段是否會出現在凸包上。從基點開始,凸包上每條相臨的線段的旋轉方向應該一致,並與掃描的方向相反。如果發現新加的點使得新線段與上線段的旋轉方向發生變化,則可判定上一點必然不在凸包上。實現時可用向量叉積進行判斷,設新加入的點為pn + 1,上一點為pn,再上一點為pn - 1。順時針掃描時,如果向量<pn - 1,pn>;與<pn,pn + 1>;的叉積為正(逆時針掃描判斷是否為負),則將上一點刪除。刪除過程需要回溯,將之前所有叉積符號相反的點都刪除,然後將新點加入凸包。 在上圖中,加入K點時,由於線段<H,K>;相對於<H,C>;為順時針旋轉,所以C點不在凸包上,應該刪除,保留K點。接著加入D點,由於線段<K,D>;相對<H,K>;為逆時針旋轉,故D點保留。按照上述步驟進行掃描,直到點集中所有的點都遍例完成,即得到凸包。 復雜度 這個演算法可以直接在原數據上進行運算,因此空間復雜度為O⑴。但如果將凸包的結果存儲到另一數組中,則可能在代碼級別進行優化。由於在掃描凸包前要進行排序,因此時間復雜度至少為快速排序的O(nlgn)。後面的掃描過程復雜度為O(n),因此整個演算法的復雜度為O(nlgn)。 ⒉1凸包最常用的凸包演算法是Graham掃描法和Jarvis步進法。 對於一個有三個或以上點的點集Q,過程如下: 計算點集最右邊的點為凸包的頂點的起點,如上圖的P3點。 Do For i = 0 To 總頂點數 計算有向向量P3->Pi If 其餘頂點全部在有向向量P3->Pi的左側或右側,則Pi點為凸包的下一頂點 Pi點加入凸包列表 GoTo 1 End If Next Exit Do 1: Loop 此過程執行後,點按極角自動順時針或逆時針排序,只需要按任意兩點的次序就可以了。而左側或右側的判斷可以用前述的矢量點積性質實現。
特殊演算法
⒉2求凸包有很多方法,不過最適合OIer和ACMer的估計還是Graham's Scan這個方法了。它的大致方法是這樣的:首先,找到所有點中最左邊的(y坐標最小的),如果y坐標相同,找x坐標最小的;以這個點為基準求所有點的極角(atan2(y-y0,x-x0)),並按照極角對這些點排序,前述基準點在最前面,設這些點為P[0]..P[n-1];建立一個棧,初始時P[0]、P[1]、P[2]進棧,對於P[3..n-1]的每個點,若棧頂的兩個點與它不構成「向左轉」的關系,則將棧頂的點出棧,直至沒有點需要出棧以後將當前點進棧;所有點處理完之後棧中保存的點就是凸包了。 如何判斷A、B、C構成的關系不是向左轉呢?如果b-a與c-a的叉乘小於0就不是。a與b的叉乘就是a.x*b.y-a.y*b.x。 上面的這個Graham的實現比我原來按照USACO里的課文寫得簡單多了,主要是它通過簡單的預處理保證了P[0]、P[1]以及P[n-1]肯定是凸包里的點,這樣就可以避免在凸包「繞回來」的時候繁雜的處理。
中心法
先構造一個中心點,然後將它與各點連接起來,按斜率遞增的方法,求出凸包上部;再按斜率遞減的方法,求出凸包下部。
水平法
從最左邊的點開始,按斜率遞增的方法,求出凸包上部;再按斜率遞減的方法,求出凸包下部。水平法較中心法減少了斜率無限大的可能,減少了代碼的復雜度。編輯本段代碼例代碼一
(在編輯器中將"_ "(下劃線+空格)替換成兩個空格即可編譯; 注意要去掉開通的雙位元組中文空格,蛋疼的網路。)

閱讀全文

與凸包演算法graham相關的資料

熱點內容
程序員送女友的相冊 瀏覽:251
壓縮文件怎麼設置打開加密 瀏覽:764
tracert命令結果詳解 瀏覽:356
唯賽思通用什麼APP 瀏覽:371
古玩哪個app好賣 瀏覽:146
u盤內容全部顯示為壓縮包 瀏覽:517
編譯固件時使用00優化 瀏覽:356
速借白條app怎麼樣 瀏覽:756
用紙張做的解壓東西教程 瀏覽:12
求圓的周長最快演算法 瀏覽:190
安卓熱點怎麼減少流量 瀏覽:270
北京代交社保用什麼app 瀏覽:855
第一眼解壓視頻 瀏覽:726
文件夾err是什麼 瀏覽:97
qt4編程pdf 瀏覽:572
區域網伺服器下如何連續看照片 瀏覽:254
經過加密的數字摘要 瀏覽:646
加密鎖9000變列印機 瀏覽:694
程序員的職業發展前途 瀏覽:639
安卓是世界上多少個程序員開發 瀏覽:45