POJ 2079 Triangle(旋转卡壳):http://poj.org/problem?id=2079
题面描述:
Time Limit: 3000MS | Memory Limit: 30000K | |
Total Submissions: 9131 | Accepted: 2704 |
Description
Input
Output
Sample Input
3 3 4 2 6 2 7 5 2 6 3 9 2 0 8 0 6 5 -1
Sample Output
0.50 27.00
题目大意:
给定一个平面上的n个点,找出以这些点为顶点的三角形且面积最大的一个,并输出它的面积。
算法分析:
由于最大的三角形总会由凸包的顶点所围成,故可以先做一个凸包,但是如果直接枚举凸包的顶点,则计算效率较低,会超时,所以此处采用旋转卡壳的算法来求解此题。
首先要枚举三角形的第一个顶点i,然后初始化第二个顶点j=i+1和第三个顶点k=j+1,循环执行k+1直到Area(i,j,k)>Area(i,j,k+1),同时更新最大面积,旋转j,k两个点,如果Area(i,j,k)<Area(i,j,k+1)且k不等于i,则执行k=k+1,否则更新面积,并执行j=j+1,如果j=i,则跳出循环,这样旋转一周,即可求得以i为顶点的最大三角形面积,时间复杂度为O(n2).
代码实现:
#include <iostream> #include <algorithm> #include <cstdio> #define N 50005 #define max(a,b) a>b?a:b using namespace std; struct node { int x,y; }dd[N]; int n,stak[N],top,top1; bool cmp(node a,node b) { return a.x<b.x||(a.x==b.x && a.y<b.y); } bool judege_right(int o,int a,int b) { int ax=dd[a].x-dd[o].x; int bx=dd[b].x-dd[o].x; int ay=dd[a].y-dd[o].y; int by=dd[b].y-dd[o].y; return bx*ay>ax*by; } double area(int o,int a,int b) { int ax=dd[a].x-dd[o].x; int bx=dd[b].x-dd[o].x; int ay=dd[a].y-dd[o].y; int by=dd[b].y-dd[o].y; return abs(bx*ay-ax*by)*1.0/2.0; } void build_map() { int i; top=0; sort(dd,dd+n,cmp); stak[top++]=0; stak[top++]=1; for(i=2;i<n;i++) { stak[top++]=i; while(top>=3) { if(judege_right(stak[top-3],stak[top-2],stak[top-1])) break; stak[top-2]=stak[top-1]; top--; } } top1=top; stak[top++]=n-2; for(i=n-3;i>=0;i--) { stak[top++]=i; while(top-top1>=2) { if(judege_right(stak[top-3],stak[top-2],stak[top-1])) break; stak[top-2]=stak[top-1]; top--; } } top--; } int main() { int i,j,k; while(scanf("%d",&n)!=EOF) { if(n==-1) { break; } for(i=0;i<n;i++) { scanf("%d%d",&dd[i].x,&dd[i].y); } build_map(); double ans=0; for(i=0;i<top;i++) { j=(i+1)%top; k=(j+1)%top; while(k!=i&&area(stak[i],stak[j],stak[k])<area(stak[i],stak[j],stak[(k+1)%top])) { k=(k+1)%top; } if(k==i) continue; int kk=(k+1)%top; while(j!=kk&&k!=i) { ans=max(ans,area(stak[i],stak[j],stak[k])); while(k!=i&&area(stak[i],stak[j],stak[k])<area(stak[i],stak[j],stak[(k+1)%top])) { k=(k+1)%top; } j=(j+1)%top; } } printf("%.2lf\n",ans); } return 0; }