旋转卡壳

#include <cstdio>
#include <iostream>
#include <cmath>
#include <utility>
#include <climits>
#include <cstring>
#include <vector>
#include <algorithm>
#define eps 1e-8
#define N_MAX 300005
using std::pair;
using std::vector;
int n;
int sign(double x){ //符号
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    return 1;
}
struct Point{
    double x,y;
    Point(double x = 0,double y = 0):x(x),y(y){}
    Point operator+(Point a){
        return Point(x + a.x,y + a.y);
    }
    Point operator-(Point a){
        return Point(x - a.x,y - a.y);
    }
    Point operator*(double t){
        return Point(x * t,y * t);
    }
    Point operator/(double t){
        return Point(x / t,y / t);
    }
    bool operator==(Point a){
        return x == a.x && y == a.y;
    }
    double lenth(){ //向量的模
        return x * x + y * y;
    }
}point[N_MAX];
vector<Point> up,down;
bool cmp(Point p1,Point p2){
    if(sign(p1.x - p2.x) == 0)return p1.y < p2.y;
    return p1.x < p2.x;
}
typedef Point Vector;
double cross(Vector A,Vector B){  // 向量外积
    return A.x * B.y - B.x * A.y;
}
double dot(Vector A,Vector B){ //向量内积
        return B.x * A.x + B.y * A.y;
}
int isclock(Vector v1,Vector v2){ // 判断v2是否在v1的顺时针方向
    if(cross(v1,v2) < 0)return -1;
    if(cross(v1,v2) == 0)return 0;
    return 1;
}
bool used[N_MAX];
int sta[N_MAX],top;
void GetConvex(){ //凸包
    std::sort(point + 1,point + n + 1,cmp);
    for(int i = 1;i <= n;i++){
        while(top >= 2 && isclock(point[sta[top - 1]] - point[sta[top - 2]],point[i] - point[sta[top - 2]]) <= 0){
            if(isclock(point[sta[top - 1]] - point[sta[top - 2]],point[i] - point[sta[top - 2]]) == -1)used[sta[--top]] = false;
            else top--;
        }
        sta[top++] = i;
        used[i] = true;
    }
    used[1] = false;
    for(int i = n;i >= 1;i--){
        if(used[i])continue;
        while(top >= 2 && isclock(point[sta[top - 1]] - point[sta[top - 2]],point[i] - point[sta[top - 2]]) <= 0)top--;
        sta[top++] = i;
    }
    top--;
}
double RotatingCalipers(){ //旋转卡壳
    if(top <= 2)return (point[1] - point[n]).lenth();
    double res = 0;
    for(int i = 0,j = 2;i < top;i++){
        Point a = point[sta[i]],b = point[sta[i + 1]];
        while(sign(cross(b - a,point[sta[j]] - a) - cross(b - a,point[sta[j + 1]] - a)) < 0)j = (j + 1) % top;
        res = std::max(res,std::max((point[sta[j]] - a).lenth(),(point[sta[j]] - b).lenth()));
    }
    return res;
}
int main(int argc,char *argv[]){
    scanf("%d",&n);
    for(int i = 1;i <= n;i++){
        double x,y;
        scanf("%lf %lf",&x,&y);
        point[i] = Point(x,y);
    }
    GetConvex();
    printf("%.0lf\n",RotatingCalipers());
    return 0;
}


#include <cstdio>
#include <iostream>
#include <cmath>
#include <utility>
#include <climits>
#include <cstring>
#include <vector>
#include <algorithm>
#define eps 1e-12
#define N_MAX 300005
#define pi acos(-1)
using std::pair;
using std::vector;
int n;
int sign(double x){ //符号
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    return 1;
}
struct Point{
    double x,y;
    Point(double x = 0,double y = 0):x(x),y(y){}
    Point operator+(Point a){
        return Point(x + a.x,y + a.y);
    }
    Point operator-(Point a){
        return Point(x - a.x,y - a.y);
    }
    Point operator*(double t){
        return Point(x * t,y * t);
    }
    Point operator/(double t){
        return Point(x / t,y / t);
    }
    bool operator==(Point a){
        return x == a.x && y == a.y;
    }
    double lenth(){ //向量的模
        return sqrt(x * x + y * y);
    }
}point[N_MAX];
vector<Point> up,down;
bool cmp(Point p1,Point p2){
    if(sign(p1.x - p2.x) == 0)return p1.y < p2.y;
    return p1.x < p2.x;
}
typedef Point Vector;
struct Line{
    Point a,b;
    Line(){}
    Line(Point a,Point b){
        this->a = a;
        this->b = b;
    }
}line[N_MAX];
double cross(Vector A,Vector B){  // 向量外积
    return A.x * B.y - B.x * A.y;
}
double dot(Vector A,Vector B){ //向量内积
        return B.x * A.x + B.y * A.y;
}
int isclock(Vector v1,Vector v2){ // 判断v2是否在v1的顺时针方向
    if(cross(v1,v2) < 0)return -1;
    if(cross(v1,v2) == 0)return 0;
    return 1;
}
double GetAngle(Vector v1,Vector v2){ // 算两向量夹角
    return acos(dot(v1,v2) / v1.lenth() / v2.lenth());
}
Vector rotate(Vector v,double angle){
    return Vector(v.x * cos(angle) + v.y * sin(angle),-v.x * sin(angle) + v.y * cos(angle));
}
Point GetPointForLine(Line X,Line Y){ // 算直线交点
    Vector v = X.a - X.b;
    Vector w = Y.a - Y.b;
    Vector u = X.a - Y.a;
    double base = (cross(w,u)) / (cross(v,w));
    return X.a + v * base;
}
double DistanceForLine(Point P,Line X){ // 算点到直线的距离
    Vector vp = X.b - X.a,vq = P - X.a;
    return fabs(cross(vp,vq))/vp.lenth();
}
double DistanceForSegment(Point P,Line X){ //点到线段的距离
    if(X.a == X.b)return (P - X.a).lenth();
    Vector v1 = X.b - X.a,v2 = P - X.a,v3 = P - X.b;
    if(sign(dot(v1,v2)) < 0) return v2.lenth();
    if(sign(dot(v1,v3)) > 0) return v3.lenth();
    return DistanceForLine(P,X);
}
Point GetProjectionInLine(Point P,Line X){ //点到直线上的投影
    Vector v = X.b - X.a;
    return X.a + v * (dot(v,P - X.a) / dot(v,v));
}
bool SegmentIntersection(Line X,Line Y){ //两线段是否相交
    double c1 = cross(X.b - X.a,Y.a - Y.b),c2 = cross(X.b - X.a,Y.b - X.a);
    double c3 = cross(Y.b - Y.a,X.b - Y.a),c4 = cross(Y.b - Y.a,X.a - Y.a);
    return sign(c1) * sign(c2) <= 0 && sign(c3) * sign(c4) <= 0;
}
pair<Point,Point> PointWithCircleAndLine(Point o,Line X,double r){ // 求圆与直线的交点
    Point o2 = o;
    o2.x += X.a.y - X.b.y;
    o2.y += X.b.x - X.a.x;
    o2 = GetPointForLine(Line(o,o2),X);
    double base = sqrt(r * r - (o2 - o).lenth() * (o2 - o).lenth());
    Vector e = (X.b - X.a) / (X.b - X.a).lenth();
    return std::make_pair(o2 - e * base,o2 + e * base);
}
bool used[N_MAX];
int sta[N_MAX],top;
void GetConvex(){
    std::sort(point + 1,point + n + 1,cmp);
    for(int i = 1;i <= n;i++){
        while(top >= 2 && isclock(point[sta[top - 1]] - point[sta[top - 2]],point[i] - point[sta[top - 2]]) <= 0){
            if(isclock(point[sta[top - 1]] - point[sta[top - 2]],point[i] - point[sta[top - 2]]) == -1)used[sta[--top]] = false;
            else top--;
        }
        sta[top++] = i;
        used[i] = true;
    }
    used[1] = false;
    for(int i = n;i >= 1;i--){
        if(used[i])continue;
        while(top >= 2 && isclock(point[sta[top - 1]] - point[sta[top - 2]],point[i] - point[sta[top - 2]]) <= 0)top--;
        sta[top++] = i;
    }
    top--;
}
Point ans[5];
double S = 1e20;
void RotatingCalipers(){
    for(int i = 0,a = 2,b = 2,c = 2;i < top;i++){
        Point d = point[sta[i]],e = point[sta[i + 1]];
        while(sign(cross(e - d,point[sta[a]] - d) - cross(e - d,point[sta[a + 1]] - d)) < 0)a = (a + 1) % top;
        while(sign(dot(e - d,point[sta[b]] - d) / (e - d).lenth() - dot(e - d,point[sta[b + 1]] - d) / (e - d).lenth()) < 0)b = (b + 1) % top;
        if(!i) c = a;
        while(sign(dot(e - d,point[sta[c]] - d) / (e - d).lenth() - dot(e - d,point[sta[c + 1]] - d) / (e - d).lenth()) > 0)c = (c + 1) % top;
        Point x = point[sta[a]],y = point[sta[b]],z = point[sta[c]];
        //std::cout << a << " " << b << " " << c << std::endl;
        double h = cross(e - d,x - d) / (e - d).lenth();
        double w = dot(y - z,e - d) / (e - d).lenth();
        if(h * w < S){
            S = h * w;
            ans[0] = d + ((e - d) / (e - d).lenth()) * (dot(e - d,y - d) / (e - d).lenth());
            ans[3] = d + ((e - d) / (e - d).lenth()) * (dot(e - d,z - d) / (e - d).lenth());
            Vector u = rotate(e - d,-pi / 2);
            ans[1] = ans[0] + (u / u.lenth()) * h;
            ans[2] = ans[3] + (u / u.lenth()) * h;
        }
    }
}
int main(int argc,char *argv[]){
    scanf("%d",&n);
    for(int i = 1;i <= n;i++){
        double x,y;
        scanf("%lf %lf",&x,&y);
        point[i] = Point(x,y);
    }
    GetConvex();
    RotatingCalipers();
    int k = 0;
    for(int i = 1;i < 4;i++){
        if(sign(ans[i].y - ans[k].y) < 0 || (sign(ans[i].y - ans[k].y) == 0 && sign(ans[i].x - ans[k].x) < 0)){
            k = i;
        }
    }
    printf("%.5lf\n",S);
    for(int i = 0;i < 4;i++,k++){
        double x = ans[k % 4].x;
        double y = ans[k % 4].y;
        if(sign(x) == 0)x = 0;
        if(sign(y) == 0)y = 0;
        printf("%.5lf %.5lf\n",x,y);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值