计算几何--凸包

叉积 Cross(vec a,vec b) a = p0p1 b = p0p2 如果p2在p0p1的左边,叉积为正


//1.每次新加入的点一定在前进方向的左边,不在的话,就将原来的点删去,直至在左边为止

hdu1348 求凸包周长 + 2 * pi * l

#include <iostream>

#include <cstdio>

#include <algorithm>

#include <cmath>

using namespace std;

const int maxn = 1000 + 5;

const double pi = acos(-1.0);

扫描二维码关注公众号,回复: 2320733 查看本文章


struct point{

    double x,y;

    bool operator < (const point &a) const{

        return x < a.x || (x == a.x && y < a.y);

    }

    point operator - (const point &a) const{

        return point{x - a.x,y - a.y};

    }

}ps[maxn],ans[maxn];

typedef point vec;

double Cross(vec a,vec b){

    return a.x * b.y - a.y * b.x;

}

int ConvexHull(point ps[],int n,point ans[])

{

    sort(ps,ps + n);

    int m = 0;

    for(int i = 0;i < n;i ++){

        while(m > 1 && Cross(ans[m - 1] - ans[m - 2],ps[i] - ans[m - 2]) < 0) m --;//还是会有一条线段上多个点

            ans[m ++] = ps[i];

    }

    //刚好逆时针

    for (int i = n - 2; i >= 0; i --) {

        while(m > 1 && Cross(ans[m - 1] - ans[m - 2],ps[i] - ans[m - 2]) < 0) m --;

        ans[m ++] = ps[i];

    }

    if(n > 1) m --;

    return m;

}

double getdis(point &a,point &b){

    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));

}

int main()

{

    int T;scanf("%d",&T);

    int n,l;

    for(int cn = 0;cn < T;cn ++){

        scanf("%d%d",&n,&l);

        for (int i = 0; i < n; i ++) {

            scanf("%lf%lf",&ps[i].x,&ps[i].y);

        }

       int sz = ConvexHull(ps, n, ans);

        double res = getdis(ans[0], ans[sz - 1]);

        for (int i = 0; i < sz - 1; i ++) {

            res += getdis(ans[i], ans[i + 1]);

        }

        res += 2 * pi * l;

        if(cn) printf("\n");

        printf("%.0lf\n",res);

        

    }

    return 0;

}

//2 分治,给定直线,每次找距离直线最远的点,该点一定在凸包上

poj3348 求凸包面积

#include <iostream>

#include <cmath>

#include <cstdio>

#include <algorithm>

using namespace std;

const int maxn = 1e4 + 5;


struct point{

    double x,y;

    bool operator < (const point &a) const{

        return x < a.x || (x == a.x && y < a.y);

    }

    point operator - (const point &a) const{

        return point{x - a.x,y - a.y};

    }

}ps[maxn];

int ans[maxn];

int num = 0;

typedef point vec;

double Corss(vec a,vec b){

    return a.x * b.y - a.y * b.x;

}

bool up[maxn],down[maxn];

double f(point &a,point &b,point &c)

{

    return a.x * b.y + c.x * a.y + b.x * c.y - c.x * b.y - b.x * a.y - a.x * c.y;

}


void ConvexHullUp(int l,int r,bool vis[])

{

    int area = 0,id = -1;

    for (int i = l + 1; i < r; i ++) {

        double t = f(ps[l], ps[r], ps[i]);

        if(t > area){

            area = t;

            id = i;

        }

    }

    if(area > 0){

        vis[id] = 1;

        ConvexHullUp(l, id, vis);

        ConvexHullUp(id, r, vis);

    }

}

void ConvexHullDown(int l,int r,bool vis[])

{

    int area = 0,id = -1;

    for (int i = l + 1; i < r; i ++) {

        double t = f(ps[l], ps[r], ps[i]);

        if(t < area){

            area = t;

            id = i;

        }

    }

    if(area < 0){

        vis[id] = 1;

        ConvexHullDown(l, id, vis);

        ConvexHullDown(id, r, vis);

    }

}

double getdis(point &a,point &b){

    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));

}

double getarea(point &p1,point &p2,point &p3){

    double a = getdis(p1, p2);

    double b = getdis(p1, p3);

    double c = getdis(p2, p3);

    double p = (a + b + c) / 2;

    return sqrt(p * (p - a) * (p - b) * (p - c));

}

int main()

{

    int n;scanf("%d",&n);

    for (int i = 0; i < n; i ++) {

        scanf("%lf%lf",&ps[i].x,&ps[i].y);

    }

    sort(ps,ps + n);

    up[0] = up[n - 1] = 1;

    down[0] = down[n - 1] = 1;

    ConvexHullUp(0,n - 1,up);

    ConvexHullDown(0, n - 1, down);

    for (int i = 0; i < n; i ++) {

        if(down[i]) ans[num ++] = i;

    }

    for (int i = n - 2; i > 0; i --) {

        if(up[i]) ans[num ++] = i;

    }

    double sum = 0;

    for (int i = 0; i < num - 2; i ++) {

        sum += getarea(ps[ans[i]],ps[ans[i + 1]],ps[ans[num - 1]]);

    }

    printf("%d\n",(int)floor(sum / 50));

    return 0;

}


猜你喜欢

转载自blog.csdn.net/sm_545/article/details/80027260
今日推荐