HDU 3934 Summer holiday 旋轉卡殼 最大三角形面積

來源:互聯網
上載者:User

//題意很簡單就是要求N個點的最大三角形的面積。。想到凸包。。一看資料,1000000,,用枚舉的話肯定會TLE。。
//花了兩天看了旋轉卡殼。。現在還是不是很懂。。。
//凸包上的點有可能3點共線啊。。。一個跟屎一樣的問題,,搞了我兩天。。暈死。。
//下次要學乖了,,,3點共線啊。。暈。。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#define pi acos(-1.0)
using namespace std;

typedef double pointper;//點座標的類型

#define POINTNUM 100005//最多點的個數
#define PREX 1e-11  //當點座標為實數型的時候用

struct node
{
 pointper x,y;
}Point[100001];

class Polygon
{
public:
 int sta[POINTNUM];//在凸包上點的座標
 node point[POINTNUM];
 bool flag[POINTNUM];
 int top,n,stab;//n為讀入的點的個數,top-1為凸包上點的個數,(0~~top-2)是凸包上點的座標,top-1和0存的都是第一個點;
 pointper x1,y1,x2,y2;
 polygon()
 {
  top=n=0;
 }
 static bool cmp(const node &A,const node &B)
 {
  return A.x<B.x||A.x==B.x&&A.y<B.y;//先根據X排序,然後根據Y排序
 }
 bool X(double x1,double y1,double x2,double y2,bool f)//f為true表示求的包括邊上的點
 {
  if(f)
   return x1*y2-x2*y1>=0.0||fabs(x1*y2-x2*y1)<PREX;
  return x1*y2-x2*y1>0.0;
 }
 double dis(node a,node b)
 {
        return sqrt((double)((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)));
 }
 double max(double a,double b)
 {
  return a>b?a:b;
 }
 double Xmult(node o,node a,node b)
 {
  return (a.x-o.x)*(b.y-o.y)-(b.x-o.x)*(a.y-o.y);
 }
 void pointselect(bool f);//求凸包上的點,f為true表示求的包括邊上的點;
 void getpoint(int i,bool f);
 void XY(int i);//輔助X()求叉乘
 double length();//求凸包的周長
 double area();//求凸包的面積;
 bool IsInPoly(double x,double y,bool f);
};

Polygon Tubao;

void Polygon::XY(int i)
{
 x1=point[i].x-point[sta[top-2]].x;
 y1=point[i].y-point[sta[top-2]].y;
 x2=point[sta[top-1]].x-point[sta[top-2]].x;
 y2=point[sta[top-1]].y-point[sta[top-2]].y;
}

void Polygon::getpoint(int i,bool f)
{
 XY(i);
 if(top==stab||X(x1,y1,x2,y2,f))
 {
  sta[top++]=i;
  flag[i]=false;
 }
 else
 {
  top--;
  flag[sta[top]]=true;
  XY(i);
  while(top>stab&&!X(x1,y1,x2,y2,f))
  {
   top--;
   flag[sta[top]]=true;
   XY(i);
  }
  sta[top++]=i;
  flag[i]=false;
 }
}
void Polygon::pointselect(bool f)
{
 int i;
 memset(flag,true,n+1);
 sort(point,point+n,cmp);
 sta[0]=0;
 sta[1]=1;
 top=2;
 flag[1]=false;
 stab=1;
 for(i=2;i<n;i++)
  getpoint(i,f);
 stab=top;
 for(i=n-2;i>=0;i--)
  if(flag[i])
   getpoint(i,f);
}

double Polygon::length()
{
 double s=0.0;
 int i;
 for(i=1;i<top;i++)
  s+=sqrt(1.0*(point[sta[i]].x-point[sta[i-1]].x)*(point[sta[i]].x-point[sta[i-1]].x)+(point[sta[i]].y-point[sta[i-1]].y)*(point[sta[i]].y-point[sta[i-1]].y));
 return s;
}
double Polygon::area()
{
 double s=0.0;
 int i;
 for(i=1;i<top;i++)
  s+=point[sta[i-1]].x*point[sta[i]].y-point[sta[i]].x*point[sta[i-1]].y;
 return fabs(s/2);
}

bool Polygon::IsInPoly(double x,double y,bool f)//double型
{
 int i;
 for(i=1;i<top;i++)
  if(!X(x-point[sta[i-1]].x,y-point[sta[i-1]].y,point[sta[i]].x-point[sta[i-1]].x,point[sta[i]].y-point[sta[i-1]].y,f))
   return false;
  return true;
}

int main()
{
 int i,j,k;
 while(scanf("%d",&Tubao.n)!=EOF)
 {
  for(i=0;i<Tubao.n;i++)
  {
   scanf("%lf %lf",&Tubao.point[i].x,&Tubao.point[i].y);
  }
  if(Tubao.n==3)//不知道我的凸包的模板為什麼處理不了3個點的情況。。
  {
   double g;
   double x1=Tubao.point[0].x-Tubao.point[1].x;
   double y1=Tubao.point[0].y-Tubao.point[1].y;
   double x2=Tubao.point[0].x-Tubao.point[2].x;
   double y2=Tubao.point[0].y-Tubao.point[2].y;
   g=fabs((x1*y2-x2*y1)/2.0);
   printf("%.2lf\n",g);
  }
  else
  {
   Tubao.pointselect(0);//凸包上的點有可能3點共線啊。。。一個跟屎一樣的問題,,搞了我兩天。。暈死。。
   double ans=0,ans1=0;
   int n=2;
   for(i=0;i<Tubao.top;i++)
   {
    ans=-1;
    n=(i+2)%Tubao.top;
    for(j=i+1;j<Tubao.top;j++)
    {
     while(Tubao.Xmult(Tubao.point[Tubao.sta[i]],Tubao.point[Tubao.sta[j]],Tubao.point[Tubao.sta[n+1]])>Tubao.Xmult(Tubao.point[Tubao.sta[i]],Tubao.point[Tubao.sta[j]],Tubao.point[Tubao.sta[n]]))
      n=(n+1)%Tubao.top;
     ans=Tubao.max(ans,Tubao.Xmult(Tubao.point[Tubao.sta[i]],Tubao.point[Tubao.sta[j]],Tubao.point[Tubao.sta[n]])); 
    }
    if(ans1<ans)
     ans1=ans;
   }
   printf("%.2lf\n",ans1*0.5);
   
  }
 }
 return 0;
}

/*
題目大意:輸入n個點的座標,計算其中最大的三角形面積

很顯然最大面積的三角形一定在這個點集的凸包上,因此先求出凸包。如果直接枚舉凸包同樣會逾時,可以藉助求凸包直徑類似的方法來求最大面積的三角形,使用旋轉卡殼方法。

枚舉三角形的第一個頂點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為頂點的最大三角形面積。

#define N 50005

#define max(a,b) a>b?a:b

#include<iostream>

#include<algorithm>

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 judge_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 (__int64)bx*ay>(__int64)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(judge_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(judge_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),n!=-1)   

       {

              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;

}
 
*/

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.