凸包
模版题: http://acm.hdu.edu.cn/showproblem.php?pid=1392(Graham算法)
#include<bits/stdc++.h> using namespace std; const int M=1e3+3; struct tu{ double x,y; tu friend operator -(tu a,tu b){ return {a.x-b.x,a.y-b.y}; } }p[M],s[M]; double X(tu a,tu b){ return a.x*b.y-a.y*b.x; } double dis(tu a,tu b){ a=a-b; return sqrt(a.x*a.x+a.y*a.y); } bool cmp(tu a,tu b){ int x=X(a-p[1],b-p[1]); if(x>0||x==0&&dis(a,p[1])<dis(b,p[1])) return 1; return 0; } int main(){ int n; while(~scanf("%d",&n)&&n){ for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y; int k=1; if(n==1){ printf("0.00\n"); continue; } else if(n==2){ printf("%.2lf\n",dis(p[1],p[2])); continue; } for(int i=2;i<=n;i++) if(p[i].y<p[k].y||p[i].y==p[k].y&&p[i].x<p[k].x) k=i; swap(p[1],p[k]); sort(p+2,p+1+n,cmp); s[1]=p[1],s[2]=p[2]; int tot=2; for(int i=3;i<=n;i++){ while(tot>=2&&X(s[tot]-s[tot-1],p[i]-s[tot-1])<=0) tot--; s[++tot]=p[i]; } double ans=dis(s[1],s[tot]); /// cout<<ans<<endl; for(int i=2;i<=tot;i++) ans+=dis(s[i],s[i-1]); printf("%.2lf\n",ans); } return 0; }
任意多边形的面积
struct tu { double x, y; }; //计算任意多边形的面积,顶点按照顺时针或者逆时针方向排列 double polygon_area(tu *p, int n) { if(n < 3) return 0; double sum = 0; p[n + 1] = p[1]; for(int i = 1; i <= n; i++) sum += p[i].x * p[i + 1].y - p[i].y * p[i + 1].x;//可以理解为不管这个多边形在哪,都以原点为分割点,就算原点在外面也可以算出,因为有正负可以抵消掉多余的 sum = fabs(sum / 2.0); return sum; }
求面积均匀的多边形重心
#include<bits/stdc++.h> using namespace std; struct node{ double x,y; node friend operator -(node a,node b) { return {a.x-b.x,a.y-b.y}; } double friend operator *(node a,node b)//对*进行重载 node*node 相当于X乘 { return a.x*b.y-a.y*b.x; } }a[1000010]; int main() { int t; cin>>t; while(t--) { int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y; double S=0,X=0,Y=0; for(int i=2;i<n;i++) { double x=(a[i]-a[1])*(a[i+1]-a[1]);//这个乘和下面的不一样,这时X乘,求出三角形面积 X+=(a[1].x+a[i].x+a[i+1].x)*x;//重心(没除以3)乘以面积 Y+=(a[1].y+a[i].y+a[i+1].y)*x; S+=x; } printf("%.2lf %.2lf\n",X/S/(double)3,Y/S/(double)3);//除以3为重心 } return 0; }
Melkman算法
例题:http://poj.org/problem?id=2187
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> using namespace std; typedef long long ll; const int M=1e5+5; struct node{ ll x,y; node friend operator-(node a,node b){ return {a.x-b.x,a.y-b.y}; } bool friend operator==(node a,node b){ return a.x==b.x&&a.y==b.y; } }a[M],p[M<<1]; bool cmp(node a,node b){ return a.x-b.x<0||a.x==b.x&&a.y-b.y<0; } ll dis(node a,node b){ node c=a-b; return c.x*c.x+c.y*c.y; } ll X(node a,node b){ return a.x*b.y-a.y*b.x; } int main(){ int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%lld%lld",&a[i].x,&a[i].y); sort(a,a+n,cmp); n=unique(a,a+n)-a; int m=0; for(int i=0;i<n;i++){ while(m>1&&X(p[m-1]-p[m-2],a[i]-p[m-2])<=0) m--; p[m++]=a[i]; } int k=m; for(int i=n-2;i>=0;i--){ while(m>k&&X(p[m-1]-p[m-2],a[i]-p[m-2])<=0) m--; p[m++]=a[i]; } n=m; if(n>1) n--; if(n==1) return puts("0"),0; if(n==2) return printf("%lld\n",dis(p[0],p[1])),0; ll ans=0; p[n]=p[0]; int j=1; for(int i=0;i<n;i++){ while(X(p[i+1]-p[i],p[j]-p[i])-X(p[i+1]-p[i],p[j+1]-p[i])<0) j=(j+1)%n; ll d1=dis(p[i],p[j]); ll d2=dis(p[i+1],p[j]); ans=max(ans,max(d1,d2)); } printf("%lld\n",ans); return 0; }
https://codeforces.com/gym/101635
分析:旋转卡壳求最小直径
#include<bits/stdc++.h> using namespace std; const int M=2e5+5; struct node{ double x,y; node friend operator -(node a,node b){ return {a.x-b.x,a.y-b.y}; } bool friend operator ==(node a,node b){ return a.x==b.x&&a.y==b.y; } }a[M],p[M<<1]; bool cmp(node a,node b){ return a.x-b.x<0||a.x==b.x&&a.y-b.y<0; } double X(node a,node b){ return a.x*b.y-a.y*b.x; } double dis(node a,node b){ node c=a-b; return c.x*c.x+c.y*c.y; } int main(){ int n; double R; scanf("%d%lf",&n,&R); for(int i=0;i<n;i++){ scanf("%lf%lf",&a[i].x,&a[i].y); } sort(a,a+n,cmp); n=unique(a,a+n)-a; //cout<<n<<endl; int m=0; for(int i=0;i<n;i++){ while(m>1&&X(p[m-1]-p[m-2],a[i]-p[m-2])<=0) m--; p[m++]=a[i]; } int k=m; for(int i=n-2;i>=0;i--){ while(m>k&&X(p[m-1]-p[m-2],a[i]-p[m-2])<=0) m--; p[m++]=a[i]; } if(n>1) m--; n=m; if(n<=2) return printf("0.000000000"),0; int j=1; double ans=2.0*R; p[n]=p[0]; for(int i=0;i<n;i++){ while(X(p[i+1]-p[i],p[j+1]-p[i])-X(p[i+1]-p[i],p[j]-p[i])>0)///每次找离直线i-i+1最远的点,也即为符合条件的点 j=(j+1)%n; double d=sqrt(dis(p[i],p[i+1])); double h=1.0*fabs(X(p[i+1]-p[i],p[j]-p[i]))/d; ans=min(ans,h); } printf("%.10f\n",ans); return 0; }