●POJ 1259 The Picnic
题链:
http://poj.org/problem?id=1259
题解:
计算几何,凸包,DP
题意:给出N($N\leq100$)个点,求出最大的凸包使得凸包里面不存在点(边上可以有)。输出最大凸包的面积。
把所有点按x从小到大排序(若x相同则按y从小到大排序)。
依次枚举每个点p,把它作为凸包的左下角来计算此时可以形成的最大凸包。
做法如下:
将p号点作为原点,取出p+1~N的点(共m=N-p个点),对这m个点按极角逆时针排序。
然后定义DP状态:
f[j][i]:表示以i,j作为当前凸壳的最后两个点时的最大面积。(p<j<i)
转移:(S(j,i,p)表示j,i,p三个点形成的三角形)
f[j][i]=max(f[k][j])+S(j,i,p) (p<k<j且 $\vec{kj}\times\vec{ji}\geq0$,即要形成凸壳)
差不多就这样,然后注意细节就好了。(反正我是弄了好久才过样例的,233)
复杂度 $O(N^4)$
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 105 #define INF 0x3f3f3f3f using namespace std; struct Point{ int x,y; Point(int _x=0,int _y=0):x(_x),y(_y){} void Read(){scanf("%d%d",&x,&y);} }D[MAXN],Q[MAXN]; typedef Point Vector; bool operator == (Point A,Point B){return A.x==B.x&&A.y==B.y;} Vector operator - (Point A,Point B){return Vector(A.x-B.x,A.y-B.y);} int operator ^ (Vector A,Vector B){return A.x*B.y-A.y*B.x;} int operator * (Vector A,Vector B){return A.x*B.x+A.y*B.y;} int GL2(Vector A){//Get_Length^2 return A*A; } bool XYcmp(Point A,Point B){return A.x-B.x<0||(A.x-B.x==0&&A.y-B.y<0);} bool PAcmp(Point A,Point B){return (A^B)>0||((A^B)==0&&GL2(A)<GL2(B));} bool inTArea(Point P,Point A,Point B){//in_Triangle_Area if(((B-A)^(P-A))<=0) return 0; if((P^B)<=0||(P^A)>0) return 0; return 1; } int F[MAXN][MAXN]; int DP(int m){ int ret=0; memset(F,0,sizeof(F)); for(int i=1;i<=m;i++) for(int j=1;j<i;j++) for(int k=j+1;k<i;k++){ if(Q[k]==Q[i]||Q[k]==Q[j]) continue; if(!inTArea(Q[k],Q[j],Q[i])) continue; F[j][i]=-INF;break; } for(int i=1;i<=m;i++) for(int j=1;j<i;j++) if(!F[j][i]){ F[j][i]=Q[j]^Q[i]; int tmp=0; for(int k=j-1;k;k--){ if(((Q[j]-Q[k])^(Q[i]-Q[j]))>=0) tmp=max(tmp,F[k][j]); if(!(Q[k]^Q[j])) break; } F[j][i]+=tmp; ret=max(ret,F[j][i]); } return ret; } int work(int n){ int m,ret=0; sort(D+1,D+n+1,XYcmp); for(int i=1;m=0,i<=n;i++){ for(int j=i+1;j<=n;j++) Q[++m]=D[j]; for(int j=1;j<=m;j++) Q[j]=Q[j]-D[i]; sort(Q+1,Q+m+1,PAcmp); ret=max(ret,DP(m)); } return ret; } int main(){ int Case,n; double ans; for(scanf("%d",&Case);Case;Case--){ scanf("%d",&n); for(int i=1;i<=n;i++) D[i].Read(); ans=1.0*work(n)/2; printf("%.1lf\n",ans); } return 0; }
Do not go gentle into that good night.
Rage, rage against the dying of the light.
————Dylan Thomas