凸包笔记

在平面直角坐标系上给你一堆点,让你从中选出一些点组成一个点集,使得它们恰好能构成一个凸多边形且全部点都在这个凸多边形内(含边界),那么选出来的这个点集就叫做这些点的凸包。

Graham算法

叉积,极角排序啥的大家肯定都会,我就不多说了,这篇博客还是以存代码为主。

具体思路就是先把所有点中最左下角的点拿出来(因为它必定在凸包上),然后其它点以它为原点极角排序,然后用一个栈维护凸包,数学证明和具体实现都很简单,我就不写了qwq

由于每个点最多出入栈一次所以是线性的时间复杂度,但是要排序所以多了个$log$。。。

时间复杂度$O(nlogn)$

代码:

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 2147483647
 8 using namespace std;
 9 struct node{
10     int x,y;
11 }a[100001],s[100001];
12 int n,k,top=1;
13 double cross(node p,node p1,node p2){
14     return (p1.x-p.x)*(p2.y-p.y)-(p1.y-p.y)*(p2.x-p.x);
15 }
16 double dis(node x,node y){
17     return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
18 }
19 bool cmp(node p1,node p2){
20     double t=cross(a[0],p1,p2);
21     if(t>0||(t==0&&dis(a[0],p1)<dis(a[0],p2)))return true;
22     return false;
23 }
24 void graham(){
25     s[0]=a[0];
26     s[1]=a[1];
27     for(int i=2;i<n;i++){
28         while(cross(s[top-1],s[top],a[i])<0&&top)top--;
29         s[++top]=a[i];
30     }
31 }
32 int main(){
33     scanf("%d",&n);
34     for(int i=0;i<n;i++){
35         scanf("%d%d",&a[i].x,&a[i].y);
36         if(i==0||a[i].y<a[k].y||(a[i].y==a[k].y&&a[i].x<a[k].x))k=i;
37     }
38     swap(a[0],a[k]);
39     sort(a+1,a+n,cmp);
40     graham();
41     for(int i=0;i<=top;i++){
42         printf("%d %d\n",s[i].x,s[i].y);
43     }
44     return 0;
45 }

旋转卡壳

来,大家跟我念:xuan2zhuan3qia3ke2

就是拿两根直线“卡”着凸包,然后乱搞一下东西qwq

几道题目(待更完):

【BZOJ1185】【HNOI2007】最小矩形覆盖

旋转卡壳乱搞

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 2147483647
 8 #define eps 1e-9
 9 using namespace std;
10 struct node{
11     double x,y;
12     node(const double _x=0,const double _y=0){x=_x,y=_y;}
13     friend bool operator <(node x,node y){return fabs(x.y-y.y)<eps?x.x<y.x:x.y<y.y;}
14     friend bool operator ==(node x,node y){return fabs(x.x-y.x)<eps&&fabs(x.y-y.y)<eps;}
15     friend bool operator !=(node x,node y){return !(x==y);}
16     friend node operator +(node x,node y){return node(x.x+y.x,x.y+y.y);}
17     friend node operator -(node x,node y){return node(x.x-y.x,x.y-y.y);}
18     friend node operator *(node x,double y){return node(x.x*y,x.y*y);}
19     friend double operator *(node x,node y){return x.x*y.y-x.y*y.x;}
20     friend double operator /(node x,node y){return x.x*y.x+x.y*y.y;}
21     friend double dis(node x,node y){return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}
22     friend double cross(node p,node p1,node p2){return (p1-p)*(p2-p);}
23 }a[100001],s[100001],ans[4];
24 int n,k,l,r,now,top=1;
25 double L,R,S,H,sq,anss=100000000000;
26 bool cmp(node p1,node p2){
27     double t=(p1-a[1])*(p2-a[1]);
28     if(t>0||(fabs(t)<eps&&dis(a[1],p1)<dis(a[1],p2)))return true;
29     return false;
30 }
31 
32 int main(){
33     scanf("%d",&n);
34     for(int i=1;i<=n;i++){
35         scanf("%lf%lf",&a[i].x,&a[i].y);
36         if(i==1||a[i]<a[k])k=i;
37     }
38     swap(a[1],a[k]);
39     sort(a+2,a+n+1,cmp);
40     s[1]=a[1];
41     for(int i=2;i<=n;i++){
42         while(top>1&&(s[top]-s[top-1])*(a[i]-s[top])<eps)top--;
43         s[++top]=a[i];
44     }
45     s[0]=s[top];
46     l=r=now=1;
47     for(int i=0;i<top;i++){
48         S=dis(s[i],s[i+1]);
49         while((s[i+1]-s[i])*(s[now+1]-s[i])-(s[i+1]-s[i])*(s[now]-s[i])>-eps)now=(now+1)%top;
50         while((s[i+1]-s[i])/(s[r+1]-s[i])-(s[i+1]-s[i])/(s[r]-s[i])>-eps)r=(r+1)%top;
51         if(!i)l=r;
52         while((s[i+1]-s[i])/(s[l+1]-s[i])-(s[i+1]-s[i])/(s[l]-s[i])<eps)l=(l+1)%top;
53         L=((s[i+1]-s[i])/(s[l]-s[i]))/S;
54         R=((s[i+1]-s[i])/(s[r]-s[i]))/S;
55         H=((s[i+1]-s[i])*(s[now]-s[i]))/S;
56         if(H<0)H=-H;
57         sq=(R-L)*H;
58         if(sq<anss){
59             anss=sq;
60             ans[0]=s[i]+(s[i+1]-s[i])*(R/S);
61             ans[1]=ans[0]+(s[r]-ans[0])*(H/dis(ans[0],s[r])); 
62             ans[2]=ans[1]-(ans[0]-s[i])*((R-L)/dis(ans[0],s[i]));
63             ans[3]=ans[2]+ans[0]-ans[1];
64         }
65     }
66     printf("%.5lf\n",anss);
67     k=0;
68     for(int i=1;i<=3;i++)if(ans[i]<ans[k])k=i;
69     for(int i=0;i<=3;i++)printf("%.5lf %.5lf\n",ans[(k+i)%4].x,ans[(k+i)%4].y);
70     return 0;
71 }

 

posted @ 2018-09-10 19:23  DCDCBigBig  阅读(183)  评论(0编辑  收藏  举报