【旋转卡壳合集】 - 凸多边形直径 - 凸多边形间最小距离 - 凸多边形最小面积外接矩形

参考资料https://blog.csdn.net/ACMaker


【凸多边形直径】POJ - 2187 - Beauty Contest

题目链接http://poj.org/problem?id=2187


#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e5+7;
const db eps=1e-7;
inline db sign(db k){if(k>eps) return 1;if(k<-eps) return -1;return 0;}
inline db dcmp(db k1,db k2){return sign(k1-k2);}
struct point{
    db x,y;
    point operator - (const point k)const{
        return (point){x-k.x,y-k.y};
    }
    int abs2(){return x*x+y*y;}
    int dis(point k){return (*this-k).abs2();}
    void print(){printf("(%f,%f)\n",x,y);}
};
db cross(point k1,point k2){
    return k1.x*k2.y-k2.x*k1.y;
}
bool cmp(point k1,point k2){
    if(dcmp(k1.x,k2.x)==0) return k1.y>k2.y;
    return k1.x<k2.x;
}
vector<point> convexHull(vector<point>p){
    int sz=p.size(),tp=0;
    if(sz<=1) return p;
    vector<point>res(sz*2);
    sort(p.begin(),p.end(),cmp);
    for(int i=0;i<sz;i++){
        while(tp>=2&&cross(res[tp-1]-res[tp-2],p[i]-res[tp-2])<eps) tp--;
        res[tp++]=p[i];
    }
    int lst=tp+1;
    for(int i=sz-2;i>=0;i--){
        while(tp>=lst&&cross(res[tp-1]-res[tp-2],p[i]-res[tp-2])<eps) tp--;
        res[tp++]=p[i];
    }
    res.resize(tp-1);
    return res;
}
int solve(vector<point>p){
    if(p.size()<=2) return p[0].dis(p[1]);
    p.push_back(p[0]);
    int res=0,j=2;
    for(int i=0;i<p.size();i++){
        while(dcmp(cross(p[i]-p[j],p[i+1]-p[j]),cross(p[i]-p[j+1],p[i+1]-p[j+1]))<0)
        	j=(j+1)%p.size();
        res=max(res,p[j].dis(p[i]));
        res=max(res,p[j].dis(p[i+1]));
    }
    return res;
}
vector<point>P;
int main()
{
    int n;
    scanf("%d",&n);
    point tmp;
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&tmp.x,&tmp.y);
        P.push_back(tmp);
    }
    P=convexHull(P);
    printf("%d\n",solve(P));
}


【凸多边形间最小距离】POJ - 3608 - Bridge Across Islands

题目链接http://poj.org/problem?id=3608


#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e5+7;
const db eps=1e-7;
const db inf=1e18;
inline int sign(db k){if(k>eps) return 1;if(k<-eps) return -1;return 0;}
inline int dcmp(db k1,db k2){return sign(k1-k2);}
int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内
struct point{
    db x,y;
    point operator + (const point k)const{
        return (point){x+k.x,y+k.y};
    }
    point operator - (const point k)const{
        return (point){x-k.x,y-k.y};
    }
    point operator * (const db k)const{
        return (point){x*k,y*k};
    }
    point operator / (const db k)const{
        return (point){x/k,y/k};
    }
    db abs2(){return x*x+y*y;}
    db abs(){return sqrt(abs2());}
    db dis(point k){return (*this-k).abs();}
    void print(){printf("(%f,%f)\n",x,y);}
};
int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
db cross(point k1,point k2){
    return k1.x*k2.y-k2.x*k1.y;
}
db dot(point k1,point k2){
    return k1.x*k2.x+k1.y*k2.y;
}
point proj(point k1,point k2,point q){ // q 到直线 k1,k2 的投影
    point k=k2-k1; return k1+k*(dot(q-k1,k)/k.abs2());
}
db disSP(point k1,point k2,point q){
    point k3=proj(k1,k2,q);
    if (inmid(k1,k2,k3)) return q.dis(k3); else return min(q.dis(k1),q.dis(k2));
}
db disSS(point k1,point k2,point k3,point k4){
    return min(min(disSP(k1,k2,k3),disSP(k1,k2,k4)),min(disSP(k3,k4,k1),disSP(k3,k4,k2)));
}
point bz;
bool cmp(point p1,point p2){
    return cross(p1-bz,p2-bz)<0;
}
db solve(vector<point>p,vector<point>q){
    bz=p[0]; sort(p.begin(),p.end(),cmp);
    bz=q[0]; sort(q.begin(),q.end(),cmp);
    int np=0,nq=0;
    for(int i=0;i<p.size();i++){
        if(p[i].y<p[np].y) np=i;
    }
    for(int i=0;i<q.size();i++){
        if(q[i].y>q[nq].y) nq=i;
    }
    p.push_back(p[0]);
    q.push_back(q[0]);
    db res=inf;
    for(int i=0;i<p.size()-1;i++){
        while(1){
            db ss=cross(q[nq]-p[np],q[nq]-p[np+1]);
            db ns=cross(q[nq+1]-p[np],q[nq+1]-p[np+1]);
            if(dcmp(ss,ns)==0){
                res=min(res,disSS(p[np],p[np+1],q[nq],q[nq+1]));
                break;
            }
            if(dcmp(ss,ns)<0){
                res=min(res,disSP(p[np],p[np+1],q[nq]));
                break;
            }
            nq=(nq+1)%(q.size()-1);
        }
        np=(np+1)%(p.size()-1);
    }
    p.resize(p.size()-1);
    q.resize(q.size()-1);
    return res;
}
vector<point>P,Q;
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0&m==0) break;
        P.clear();Q.clear();
        point tmp;
        for(int i=1;i<=n;i++){
            scanf("%lf%lf",&tmp.x,&tmp.y);
            P.push_back(tmp);
        }
        for(int i=1;i<=m;i++){
            scanf("%lf%lf",&tmp.x,&tmp.y);
            Q.push_back(tmp);
        }
        db ans=min(solve(P,Q),solve(Q,P));
        printf("%.5f\n",ans);
    }
}

【凸多边形最小面积外接矩形】HDU - 5251 - 矩形面积

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5251


#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
typedef long long ll;
typedef double db;
const db eps=1e-7;
const db inf=1e18;
int sign(db k){if(k>eps) return 1;if(k<-eps) return -1;return 0;}
int dcmp(db k1,db k2){return sign(k1-k2);}
struct point{
    db x,y;
    point operator - (const point k)const{
        return (point){x-k.x,y-k.y};
    }
    point operator + (const point k)const{
        return (point){x+k.x,y+k.y};
    }
    point operator * (const db k)const{
        return (point){x*k,y*k};
    }
    point operator / (const db k)const{
        return (point){x/k,y/k};
    }
    db abs(){return sqrt(x*x+y*y);}
    db dis(point k){return (*this-k).abs();}
    void print(){printf("(%f,%f)\n",x,y);}
};
db cross(point k1,point k2){
    return k1.x*k2.y-k1.y*k2.x;
}
db dot(point k1,point k2){
    return k1.x*k2.x+k1.y*k2.y;
}
bool cmp(point k1,point k2){
    if(dcmp(k1.x,k2.x)==0) return k1.y<k2.y;
    return k1.x<k2.x;
}
vector<point> convexHull(vector<point>p){
    if(p.size()<=1) return p;
    int sz=p.size(),tp=0;
    vector<point>res(sz*2);
    sort(p.begin(),p.end(),cmp);
    for(int i=0;i<sz;i++){
        while(tp>=2&&cross(res[tp-1]-res[tp-2],p[i]-res[tp-2])<eps) tp--;
        res[tp++]=p[i];
    }
    int lst=tp+1;
    for(int i=sz-1;i>=0;i--){
        while(tp>=lst&&cross(res[tp-1]-res[tp-2],p[i]-res[tp-2])<eps) tp--;
        res[tp++]=p[i];
    }
    res.resize(tp-1);
    return res;
}
db sovle(vector<point>p){
    p.push_back(p[0]);
    db res=inf;
    int up=1,le=1,ri=1;
    bool fst=true;
    for(int i=0;i<p.size()-1;i++){
        while(dcmp(cross(p[up]-p[i],p[up]-p[i+1]),cross(p[up+1]-p[i],p[up+1]-p[i+1]))<=0) up=(up+1)%(p.size()-1);
        while(dcmp(dot(p[i+1]-p[i],p[ri]-p[i]),dot(p[i+1]-p[i],p[ri+1]-p[i]))<=0) ri=(ri+1)%(p.size()-1);
        if(fst) le=up,fst=false;
        while(dcmp(dot(p[i]-p[i+1],p[le]-p[i+1]),dot(p[i]-p[i+1],p[le+1]-p[i+1]))<=0) le=(le+1)%(p.size()-1);
        db len=p[i].dis(p[i+1]);
        db cro=cross(p[up]-p[i],p[up]-p[i+1]);
        db dt1=dot(p[i+1]-p[i],p[ri]-p[i]);
        db dt2=dot(p[i]-p[i+1],p[le]-p[i+1]);
        res=min(res,cro*(dt1+dt2)/len/len-cro);
    }
    return res;
}
vector<point>P;
int main()
{
    int t,n,cs=0;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        point tmp;
        P.clear();
        for(int i=1;i<=n*4;i++){
            scanf("%lf%lf",&tmp.x,&tmp.y);
            P.push_back(tmp);
        }
        P=convexHull(P);
        printf("Case #%d:\n",++cs);
        printf("%.0f\n",sovle(P));
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值