小棕圈地 凸包旋轉卡殼

2021-09-26 08:14:54 字數 1954 閱讀 3020

問題描述

小粽家裡有一塊地,地上有 n 個木樁。小粽家的地可以看作是乙個平面,並且小粽知道每個木樁的座標 (xi,yi)。

小粽很喜歡四邊形,現在她想從這些木樁中選出 4 個來圍成乙個四邊形(這個四邊形為簡單多邊形,即每條邊不能和自己相交,但不一定要為凸四邊形),並使得這個四邊形的面積最大。請你幫小粽算出這個最大值是多少。

輸入格式

第一行乙個正整數 n 表示木樁的大小。

接下來 n 行,第 i 行位兩個實數 xi,yi,描述了第 i 個木樁的座標。

輸出格式

輸出一行乙個實數,表示圍出的最大的四邊形的面積。保留三位小數。
輸入樣例1

5

0 01 0

1 10 1

0.5 0.5

輸出樣例1

1.000
資料範圍及約定

20% 的資料滿足 n ≤100;

60% 的資料滿足 n ≤400;

80% 的資料滿足 n ≤1500;

100% 的資料滿足 n ≤5000,所有座標都在 int 範圍內。

提示[顯然,答案是在凸包上的]

[可以考慮列舉一條對角線,再設法確定另外兩點的位置,例如注意到點的位置具有單峰性。]

[更可考慮求對角線與凸包的切點,利用單調性均攤複雜度]

法一:暴力列舉法

列舉四個點。n4

法二:對角線列舉法

列舉兩個點 n3

法三:單調性的函式可以用三分法求取最大值。

n2 logn

法四:旋轉卡殼法

利用凸多邊形的性質。

先考慮子問題:對於乙個凸多邊形,如何在其中找乙個面積最大的三角形。

固定三角形其中乙個點,列舉另乙個底邊另乙個點。底邊確定,在切點可以達到最大值。利用暴力確定切點在**。且由於該極值點存在單調性。

兩重迴圈,列舉對角線就可以了。時間複雜度為n2

助教的旋轉凸包(順時針)**寫法如下:

double solve(point p, int n)

void read()

void print() };

point operator + (const point& a, const point& b)

point operator - (const point& a, const point& b)

double cross(point a, point b)

bool cmp(const point& a, const point& b)

//求上凸殼

int t=m;

for(int i=n-2; i>=0; --i)

// for(int i=0; icross(p[a]-p[i],p[j]-p[i]) )

a++;

while ( /*(b+1)%n!=i &&*/ cross(p[j]-p[i],p[b+1]-p[i])>cross(p[j]-p[i],p[b]-p[i]) )

b++;

ans = max(ans,cross(p[j]-p[i],p[b]-p[a]));}}

return ans/2;

}/* **********== **實現結束 ***********/

#define maxn 5000

point p[2 * maxn + 10], ch[2 * maxn + 10];

int main()

凸包問題 旋轉卡殼

1978年,m.i.shamos在 computational ceometry 中介紹了一種尋找凸多邊形直徑的線性演算法。1.支撐線 如果一條直線l,通過凸多邊形p的乙個頂點,且多邊形在這條直線的一側,稱l是p的支撐線。2.對踵 zhong,三聲 點 如果過凸包上的兩個點可以畫一對平行直線,使凸包...

模板 凸包 旋轉卡殼

模板 凸包 旋轉卡殼 lrj 訓練指南 p272 對於個點按照 x 從小到大排序,再按照 y 點從小到大排序,刪除重複的點後,得到序列 p0,p1,p2.把 p0 和 p1 放入凸包。從p2開始,當新點在凸包 前進 方向的左邊時繼續,否則依次刪除最近加入凸包的點,直到新點在左邊 ps 判斷用叉積即可...

旋轉卡殼 凸包的直徑

poj 2187 直接求直徑ok 多邊形的直徑被定義為多邊形上任意兩點間的最大距離的值。在多邊形上,決定直徑的點可能不止一對。事實上,如果乙個多邊形含有n個頂點,那麼就最多有 n 對 直徑點對 在。上圖所示的是乙個簡單的多邊形直徑的例項。直徑點對在圖中是被平行的切線 用紅色表示 穿過的黑點.直徑是用...