1. 程式人生 > >【BZOJ1069】【SCOI2007】最大土地面積 凸包 單調性

【BZOJ1069】【SCOI2007】最大土地面積 凸包 單調性

連結:

#include <stdio.h>
int main()
{
    puts("轉載請註明出處[輾轉山河弋流歌 by 空灰冰魂]謝謝");
    puts("網址:blog.csdn.net/vmurder/article/details/46591735");
}

題解:

先求凸包,然後:

列舉點 i ,然後對於 點 j 得到的 ij (有序) 中間的點,以及 ji (有序) 中間的點,都是單調的。

程式碼:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream> #include <algorithm> #define N 2050 #define eps 1e-7 using namespace std; struct Point { double x,y; void read(){scanf("%lf%lf",&x,&y);} Point(double _x=0,double _y=0):x(_x),y(_y){} bool operator < (const Point &A)const {return x==A.x?y<A.y:x<A.x;} double
operator - (const Point &A)const {return sqrt((x-A.x)*(x-A.x)+(y-A.y)*(y-A.y));} }p[N],Zero; int n; double xmul(const Point &A,const Point &B,const Point &C) {return (C.y-A.y)*(B.x-A.x)-(B.y-A.y)*(C.x-A.x);} struct qiu_tu_bao {// 名字就是這麼屌,不服你來打我啊 int stk1[N],top1,stk2[N],top2; Point tp[N]; void
work() { int i; stk1[top1=1]=1; for(i=2;i<=n;i++) { while(top1>1&&xmul(p[stk1[top1-1]],p[stk1[top1]],p[i])>-eps)top1--; stk1[++top1]=i; } stk2[top2=1]=n; for(i=n-1;i;i--) { while(top2>1&&xmul(p[stk2[top2-1]],p[stk2[top2]],p[i])>-eps)top2--; stk2[++top2]=i; } n=0; for(i=1;i<top1;i++)tp[++n]=p[stk1[i]]; for(i=1;i<top2;i++)tp[++n]=p[stk2[i]]; memcpy(p,tp,sizeof(Point)*(n+1)); } }qtb; int f[N][N]; #define rig(x,y) ((x+y - 1)%n+1) #define lef(x,y) ((x-y+n-1)%n+1) inline double Area(int l,int r,int x) { double ret=xmul(Zero,p[l],p[r]); ret+=xmul(Zero,p[r],p[x]); ret+=xmul(Zero,p[x],p[l]); return ret; } inline bool check(int l,int r,int a,int b) {return Area(l,r,a)<Area(l,r,b);} int main() { int i,j,k; int a,b,c; Zero=Point(0,0); scanf("%d",&n); for(i=1;i<=n;i++)p[i].read(); sort(p+1,p+n+1); qtb.work(); for(i=1;i<=n;i++) { f[i][rig(i,2)]=rig(i,1); for(j=rig(i,3);rig(j,1)!=i;j=rig(j,1)) { f[i][j]=f[i][lef(j,1)]; while(rig(f[i][j],1)!=j&& check(i,j,f[i][j],f[i][j]+1))f[i][j]++; } } double ans=0.0; for(i=1;i<=n;i++)for(j=rig(i,2);rig(j,1)!=i;j=rig(j,1)) ans=max(ans,Area(i,j,f[i][j])+Area(i,f[j][i],j)); printf("%.3lf\n",ans/2.0); return 0; }