Wall POJ - 1113 凸包模板
要求包围所有n个点并且距所有点距离大于L的多边形周长
这个多边形的周长可以通过凸包上的边做平移加上一个半径L的圆辅助转向得到
所以就是求凸包周长加上圆周长
主要是为了试试凸包的接口,实现用的是Graham,应该是单调栈吧?
//#include<bits/stdc++.h> //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; const double pi=acos(-1.0); #define ll long long #define pb push_back const int maxn=1e3+56; const double eps=1e-6; int sgn(double x){ if(fabs(x)<eps)return 0; if(x<0)return -1; else return 1; } struct Point{ double x,y; void input(){ scanf("%lf%lf",&x,&y); } Point(){} Point(double _x,double _y){x=_x;y=_y;} double distance(Point p){ return hypot(x-p.x,y-p.y); } Point operator +(const Point &b)const{ return Point(x+b.x,y+b.y); } Point operator -(const Point &b)const{ return Point(x-b.x,y-b.y); } double operator *(const Point &b)const{ return x*b.x+y*b.y; } Point operator *(const double &k)const{ return Point(x*k,y*k); } Point operator /(const double &k)const{ return Point(x/k,y/k); } double operator^(const Point &b)const{ return x*b.y-y*b.x; } bool operator ==(Point b)const{ return sgn(x-b.x)==0 && sgn(y-b.y)==0; } bool operator < (Point b)const{ return sgn(x-b.x)==0?sgn(y-b.y)<0:x<b.x; } double len(){return hypot(x,y);} double len2(){ return x*x+y*y; } Point trunc(double r){ double l=len(); if(!sgn(l))return *this; r/=l; return Point(x*r,y*r); } }; struct Line{ Point s,e; Line(){} Line (Point _s,Point _e){ s=_s;e=_e; } Line(Point p,double angle){//与x轴夹角 s=p; if(sgn(angle-pi/2)==0)e=(s+Point(0,1)); else e=(s+Point(1,tan(angle))); } double length(){return s.distance(e);} double dispointtoline(Point p){ return fabs((p-s)^(e-s))/length(); } double dispointtoseg(Point p){ if(sgn((p-s)*(e-s))<0 || sgn((p-e)*(s-e))<0) return min(p.distance(s),p.distance(e)); return dispointtoline(p); } Point lineprog(Point p){ return s+( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) ); } }; struct polygon{ int n; Point p[maxn]; Line l[maxn]; void input(int _n){ n=_n;for(int i=0;i<n;i++)p[i].input(); } void add(Point q){p[n++]=q;}; void getline(){ for(int i=0;i<n;i++){ l[i]=Line(p[i],p[(i+1)%n]); } } struct cmp{ Point p; cmp(const Point &p0){p=p0;} bool operator()(const Point&aa,const Point&bb){ Point a=aa,b=bb; int d=sgn( (a-p)^(b-p) ); if(d==0)return sgn(a.distance(p)-b.distance(p))<0; return d>0; } }; void norm(){ Point mi=p[0]; for(int i=1;i<n;i++)mi=min(mi,p[i]); sort(p,p+n,cmp(mi)); } void Graham(polygon &convex){ norm(); int &top=convex.n; top=0; if(n==1){ top=1;convex.p[0]=p[0]; return; } if(n==2){ top=2;convex.p[0]=p[0];convex.p[1]=p[1]; if(convex.p[0]==convex.p[1])top--;return; } convex.p[0]=p[0]; convex.p[1]=p[1]; top=2; for(int i=2;i<n;i++){ while(top>1 && sgn((convex.p[top-1]-convex.p[top-2])^ (p[i]-convex.p[top-2]))<=0)top--; convex.p[top++]=p[i]; } if(convex.n==2 && (convex.p[0]==convex.p[1]))convex.n--; } double getcircumference(){ double sum=0; for(int i=0;i<n;i++)sum+=p[i].distance(p[(i+1)%n]); return sum; } }; int main(){ int n,r; while(~scanf("%d%d",&n,&r)){ polygon now; now.input(n); polygon convex; now.Graham(convex); printf("%d\n",(int)round(convex.getcircumference()+pi*2*r)); } }
贴一个不用kb模板的轻量化板子:
//#include<bits/stdc++.h> //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; const double pi=acos(-1.0); #define ll long long #define pb push_back #define sqr(a) ((a)*(a)) #define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)) const int maxn=1e3+56; const int inf=0x3f3f3f3f; struct Point{ double x,y; int v,l; Point(double a=0,double b=0){x=a;y=b;} bool operator<(Point b)const{ return y<b.y||(y==b.y && x<b.x); } }p[maxn],ch[maxn<<1],tmp[maxn]; double mult(Point a,Point b,Point o){ return(a.x-o.x)*(b.y-o.y)>=(b.x-o.x)*(a.y-o.y); } double Graham(Point p[],int n,Point res[]){ //返回凸包周长 int top=1; sort(p,p+n); if(n==0)return 0;res[0]=p[0]; if(n==1)return 0;res[1]=p[1]; if(n==2)return dis(p[0],p[1])*2; res[2]=p[2]; for(int i=2;i<n;i++){ while(top && (mult(p[i],res[top],res[top-1]))) top--; res[++top]=p[i]; } int len=top; res[++top]=p[n-2]; for(int i=n-3;i>=0;i--){ while(top!=len && (mult(p[i],res[top],res[top-1]))) top--; res[++top]=p[i]; } double c=dis(res[0],res[top-1]); for(int i=0;i<top-1;i++){ c+=dis(res[i],res[i+1]); } return c; } int n,kase; int main(){ while(scanf("%d",&n)&&n){ for(int i=0;i<n;i++){ scanf("%lf%lf%d%d",&p[i].x,&p[i].y,&p[i].v,&p[i].l); } int min_cut=inf,min_val=inf,ans=0; double res_len=0; for(int bit=0;bit<(1<<n);bit++){ int res=0,cut_val=0; double cut_len=0; for(int i=0;i<n;i++){ if(bit & (1<<i)){ cut_len+=p[i].l; cut_val+=p[i].v; }else{ tmp[res].x=p[i].x; tmp[res++].y=p[i].y; } } if(cut_val>min_val)continue; double c=Graham(tmp,res,ch); if(cut_len>=c){ if(cut_val<min_val || (cut_val==min_val && n-res<min_cut)){ ans=bit; min_val=cut_val; min_cut=n-res; res_len=cut_len-c; } } } if(kase)puts(""); printf("Forest %d\n",++kase); printf("Cut these trees:"); for(int i=0;i<n;i++) if(ans&(1<<i)) printf(" %d",i+1); printf("\nExtra wood: %.2f\n",res_len); } }