POJ1113 Wall 凸包演算法學習)

2022-06-26 09:00:12 字數 3127 閱讀 4088

題意:

給你乙個由n個點構成的多邊形城堡(看成二維),按順序給你n個點,相鄰兩個點相連。

讓你圍著這個多邊形城堡建乙個圍牆,城堡任意一點到圍牆的距離要求大於等於l,讓你求這個圍牆的最小周長(看成二維平面)(結果四捨五入

分析:

凸包問題和這個問題的差別就在於:凸包問題沒有「城堡任意一點到圍牆的距離要求大於等於l」這個要求

凸包:找到乙個凸多邊形把這n個點形成的多邊形圍起來,找到的那個周長最小的凸多邊形就是我們所求的凸包

那麼這個問題怎麼在凸包的基礎上解決呢?

我們考慮l,對於求出的凸多邊形,對於它的頂點x,可以證明每個x附近需要增加一定的圓弧來保證頂點到圓弧的距離大於等於l,

所有x的圓弧角度之和為pi,將凸包平移與圓弧連線成封閉圖案,最終 ans=凸包+2*pi*l。如下圖(參考:

上圖中黑色實線連起來的多邊形就是題目給出的n個點形成的多邊形

我們就是要在這個基礎上滿足題目「城堡任意一點到圍牆的距離要求大於等於l」要求

如上圖所示,也就只需要多加4段圓弧就可以滿足題目需求,答案也就是ans=凸包+2*pi*l

凸包怎麼求(參考:

這裡我們使用graham scan演算法來實現,此演算法能夠在o(nlogn)的時間內找到凸包。

這裡說一下二維平面下叉積的幾何意義:對於二維向量a=(x1,y2)和b=(x2,y2),a×b定義為x1*y2-y1*x2。而它的幾何意義就是|a||b|sin<a,b>。如果ab夾角小於180度(逆時針),那麼這個值就是正值,大於180度就是負值。需要注意的是,左乘和右乘是不同的。這裡給出幾個例子

我認為這個sin<a,b>就是:a向量按照逆時針移動到b向量同方向的角度

graham scan演算法過程:

graham scan演算法的做法是先定下乙個起點,一般是最左邊的點和最右邊的點(需要排序後選擇起點),然後乙個個點掃過去,如果新加入的點和之前已經找到的點所構成的「殼」凸性沒有變化,就繼續掃,否則就把已經找到的最後乙個點刪去,再比較凸性,直到凸性不發生變化。分別掃瞄上下兩個「殼」,合併在一起,凸包就找到了。

我們找下「殼」,上下其實是一樣的。首先加入兩個點a和c:

然後插入第三個點g,並計算ac×cg的叉積,卻發現叉積小於0,也就是說逆時針方向上∠acg大於180度,於是刪去c點,加入g點:

然後就是依照這個步驟便能加入d點。在ad上方是以d為起點。就能夠找到agd和dfea兩個凸殼。合併就得到了凸包。

關於掃瞄的順序,有座標序和極角序兩種。座標序是比較兩個點的x座標,如果小的先被掃瞄(掃瞄上凸殼的時候反過來);如果兩個點x座標相同,那麼就比較y座標,小的先被掃瞄(掃瞄上凸殼的時候也是反過來)。極角序使用arctan2函式的返回值進行比較

給出poj1113:wall**:

1 #include2 #include

3 #include4 #include5 #include6 #include7 #include8 #include9

using

namespace

std;

10const

int maxn=1e3+10;11

const

double pi=acos(-1.0); //

180度的弧度制

12const

double eps=1e-6;13

struct

cpoint

1417 cpoint(double xx,double

yy):x(xx),y(yy){}

18 cpoint friend operator -(cpoint a,cpoint b)

1922

double friend operator ^(cpoint a,cpoint b)

2326

bool friend operator

2731

}point[maxn];

32double

dist(cpoint a,cpoint b)

3336

int sign(double

x)37

42bool

cmp(cpoint a,cpoint b)

4348

intn,l;

49double

graham()

5065

for(int i=1;ii)

6670 res+=dist(point[que[1

]],point[que[top]]);

71 res+=2.0*pi*l;

72return

res;73}

74int

main()

7582

return0;

83 }

POJ 1113 Wall 圍牆 凸包

題意 給出一系列的點,在凸包外面l公尺建造圍牆,求圍牆的長度。其實就是裸凸包 半徑l的圓周長。這題卡了一下午.由於裡面的精度有些問題.後面輸出最好用 f不要用lf和int轉換.第一次做凸包,感覺還好.author illuz blog file poj1113.cpp create date 201...

POJ 1113 Wall 凸包周長

題意 給定n nn個城堡的座標,要求建設連續的圍牆,且圍牆上任意一點距離任意城堡距離不小於l ll,求圍牆的最小長度。求出這些點的凸包,答案即凸包長度加上乙個半徑為l ll的圓的周長,即對於凸包的邊,在距離凸包邊l ll處建設平行的圍牆即可,而對於拐角處,畫半徑為l ll的圓即可,最後各個拐角處可以...

POJ 1113 Wall 凸包 思維

1.題意 給出n個點,讓你建立一圈圍牆,將n個點圍起來並且,每個點距離圍牆都 l,讓求在這個條件下的最小圍牆周長 2.分析 最小周長,首先想到凸包,但是這裡有個距離問題 我們最初想的,凸包周長整體外擴l 但是我們發現,每個凸包頂點,到圍牆頂點的距離 l,浪費了一部分 如果走這段弧長,假設有n個頂點,...