標籤:style os for ar amp size on sp
給出一個點集,求頂點在點集中的最大的三角形面積。
我們知道這三角形的三個點肯定在凸包上,我們求出凸包之後不能枚舉,因為題目n比較大,枚舉的話要O(n^3)的數量級,所以採用旋轉卡殼的做法:
首先枚舉三角形的第一個頂點i, 初始化第二個頂點j=i+1和第三個頂點k=j+1,對k進行迴圈,直到找到第一個k使得cross(i,j,k)>cross(i,j,k+1),如果k==i進入下一次迴圈。
對j,k進行旋轉,每次迴圈之前更新最大值,然後固定一個j,同樣找到一個k使得cross(i,j,k)>cross(i,j,k+1)。對j進行++操作,繼續進行下一次,知道j==k‘(對j,k旋轉之前的(k+1)%n)或k==i為止。
double rotating_calipers(vector<Point>& points){ vector<Point> p = ConvexHull(points); int n = p.size(); p.push_back(p[0]); double ans = 0; for(int i=0; i<n; ++i) { int j = (i+1)%n; int k = (j+1)%n; //當Area(P[i], p[j], p[k+1]) <= Area(p[i], p[j], p[k]) 時停止旋轉 //即Cross(p[j]-p[i], p[k+1]-p[i]) - Cross(p[j]-p[i], p[k]-p[i]) <= 0 //根據Cross(A,B) - Cross(A,C) = Cross(A,B-C) //化簡得Cross(p[j]-p[i], p[k+1] - p[k]) <= 0 while(k!=i && Cross(p[j]-p[i], p[k+1]-p[k]) > 0) k = (k+1) % n; if(k==i) continue; int kk = (k+1) % n; while(j!=kk && k!=i) { ans = max(ans, Cross(p[j]-p[i], p[k]-p[i])); while(k!=i && Cross(p[j]-p[i], p[k+1]-p[k]) > 0) k = (k+1) % n; j = (j+1) % n; } } return ans*0.5;}