惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
博客园 - 【当耐特】
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
D
Docker
GbyAI
GbyAI
酷 壳 – CoolShell
酷 壳 – CoolShell
WordPress大学
WordPress大学
The Cloudflare Blog
雷峰网
雷峰网
A
About on SuperTechFans
小众软件
小众软件
博客园 - Franky
博客园 - 聂微东
F
Full Disclosure
大猫的无限游戏
大猫的无限游戏
C
Check Point Blog
MongoDB | Blog
MongoDB | Blog
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
V2EX
Engineering at Meta
Engineering at Meta
宝玉的分享
宝玉的分享
aimingoo的专栏
aimingoo的专栏
量子位
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
罗磊的独立博客
Martin Fowler
Martin Fowler
D
DataBreaches.Net
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
Secure Thoughts
Project Zero
Project Zero
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tailwind CSS Blog
S
Schneier on Security
Blog — PlanetScale
Blog — PlanetScale
The Hacker News
The Hacker News
Spread Privacy
Spread Privacy
Security Latest
Security Latest
NISL@THU
NISL@THU
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
CXSECURITY Database RSS Feed - CXSecurity.com
J
Java Code Geeks

博客园 - woodfish

偏序集的Dilworth定理 XJOJ历经2个月终于完成啦~~ fork()调用的一个趣题 实现google那种输入框提示的功能 POJ 3691 安徽第二题 有限状态自动机+DP 哈尔滨赛区网络预选赛总结 [计算几何]点集中的点能组成多少个正方形 [计算几何]POJ 1375 点对圆的切线+线段重叠 [计算几何]POJ 1556 判断线段相交+Dijkstra [计算几何] POJ 1873 暴力+凸包 [计算几何]POJ 1266 三角形的外接圆 圆的参数方程 POJ 1026 置换群 [计算几何]POJ 1031 计算点对多边形的偏转角度 [计算几何]POJ3608 求2个不相交凸包的最短距离 [计算几何]凸包的旋转卡壳算法 C++禁止一个类被继承的技术 C与汇编的接口技术 计算位数的3种方法 避免使用条件分支
[计算几何]POJ2079 求点集中面积最大的三角形
woodfish · 2008-09-01 · via 博客园 - woodfish

http://acm.pku.edu.cn/JudgeOnline/problem?id=2079

如果枚举3个点再算面积,必然超时。

很显然的最大面积的三角形的三个顶点必然是这个点集的凸包上的点,因此先求出凸包。

如果求出凸包仍然枚举,一样会超时。

这个可以借助求凸包直径类似的方法来求最大面积的三角形,使用旋转卡壳方法。

枚举三角形的第一个顶点i,

然后初始第二个顶点j=i+1,第三个顶点k=j+1,

循环k+1直到Area(i,j,k)>Area(i,j,k+1)

更新面积的最大值,下面就开始旋转卡壳了(旋转j,k两个点)

(1)如果Area(i,j,k)<Area(i,j,k+1)且k!=i,则k=k+1,否则转(2)

(2)更新面积,j=j+1,如果j=i,跳出循环

这样旋转一圈后,求得的面积就是以i为顶点的最大三角形的面积了。

时间复杂度是O(n^2)

//author:chenkun
//旋转卡壳!
#include <cstdio>
#include 
<cmath>const int MAXN=50000;struct point {
    
int x, y;
} p[MAXN
+1],h[MAXN+1];double distance(const point& p1,const point& p2) {
   
return sqrt( (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
double multiply(const point& sp,const point& ep,const point& op) {
      
return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
}
int partition(point a[],int p,int r) {
    
int i=p,j=r+1,k;
    
double ang,dis;
    point R,S;
    k
=(p+r)/2;
    R
=a[p];
    a[p]
=a[k];
    a[k]
=R;
    R
=a[p];
    dis
=distance(R,a[0]);
    
while(1) {
        
while(1) {
            
++i;
            
if(i>r) {
                i
=r;
                
break;
            }
            ang
=multiply(R,a[i],a[0]);
            
if(ang>0)
                
break;
            
else if(ang==0) {
                
if(distance(a[i],a[0])>dis)
                
break;
            }
        }
        
while(1) {
             
--j;
            
if(j<p) {
                j
=p;
                
break;
            }
            ang
=multiply(R,a[j],a[0]);
            
if(ang<0)
                
break;
            
else if(ang==0) {
                
if(distance(a[j],a[0])<dis)
                    
break;
            }
        }
        
if(i>=j)break;
        S
=a[i];
        a[i]
=a[j];
        a[j]
=S;
    }
    a[p]
=a[j];
    a[j]
=R;
    
return j;
}
void anglesort(point a[],int p,int r) {
   
if(p<r) {
      
int q=partition(a,p,r);
      anglesort(a,p,q
-1);
      anglesort(a,q
+1,r);
   }
}
//对PointSet求凸包,点数为n,凸包上的点保存在ch中,点数位len
void Graham_scan(point PointSet[],point ch[],int n,int &len) {
    
int i,k=0,top=2;
    point tmp;
    
for(i=1;i<n;i++)
        
if ( PointSet[i].x<PointSet[k].x ||
            (PointSet[i].x
==PointSet[k].x) && (PointSet[i].y<PointSet[k].y) )
               k
=i;
    tmp
=PointSet[0];
    PointSet[
0]=PointSet[k];
    PointSet[k]
=tmp;
    anglesort(PointSet,
1,n-1);
    
if(n<3) {
        len
=n;
        
for(int i=0;i<n;i++) ch[i]=PointSet[i];
        
return ;
    }
    ch[
0]=PointSet[0];
    ch[
1]=PointSet[1];
    ch[
2]=PointSet[2];
    
for (i=3;i<n;i++) {
        
while (multiply(PointSet[i],ch[top],ch[top-1])>=0) top--;
            ch[
++top]=PointSet[i];
    }
    len
=top+1;
}
double Area(int i,int j,int k) {
    
return multiply(h[j],h[k],h[i])/2;
}

inline 

double max(double a,double b){return a>b?a:b;}
int main() {
    
int n;
    
while(scanf("%d",&n)!=EOF&&n!=-1) {
        
for(int i=0;i<n;i++)
            scanf(
"%d %d",&p[i].x,&p[i].y);
        
int len;
        Graham_scan(p,h,n,len);
        
//for(int i=0;i<len;i++)
        
//    printf("%d %d\n",h[i].x,h[i].y);

        
double ans=0;
        
for(int i=0;i<len;i++) {
            
int j=(i+1)%len;
            
int k=(j+1)%len;
            
while(k!=i&&Area(i,j,k)<Area(i,j,(k+1)%len)) {
                k
=(k+1)%len;
            }
            
if(k==i) continue;
            
int kk=(k+1)%len;
            
while(j!=kk&&k!=i) {
                ans
=max(ans,Area(i,j,k));
                
while(k!=i&&Area(i,j,k)<Area(i,j,(k+1)%len)) {
                    k
=(k+1)%len;
                }
                j
=(j+1)%len;
            }
        }

        printf(

"%.2f\n",ans);
    }
    
return 0;
}