[HDU4316]Mission Impossible(计算几何/凸包/半平面交)

题目链接:

HDU4316

计算几何太duliu了~

题目大意:空间中有一个物体,上空有\(3\)个摄像头拍摄地面,求摄像头公共盲区面积大小

首先求出每一个摄像头的盲区:

将物体的每一个点投影到地面再求凸包即可。

然后将\(3\)个凸包的每一条边都拿来一起做一次半平面交,求出公共盲区

最后三角剖分求面积就好了。

代码:

#include <cmath>
#include <cstdio>
#include <vector>
#include <algorithm>

const double Eps=1e-8;
inline double Abs(double x){return x>=0?x:-x;}
inline int Sign(double x){return Abs(x)<Eps?0:(x>0?1:-1);}

typedef struct Point
{
    double x,y;
    inline Point operator+(Point o){return (Point){x+o.x,y+o.y};}
    inline Point operator-(Point o){return (Point){x-o.x,y-o.y};}
    inline Point operator*(double k){return (Point){x*k,y*k};}
    inline bool operator<(Point o){return Sign(x-o.x)?x<o.x:y<o.y;}
    inline bool operator==(Point o){return !Sign(x-o.x)&&!Sign(y-o.y);}
}Vector;
inline double Dot(Vector A,Vector B){return A.x*B.x+A.y*B.y;}
inline double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}

struct Point_3D{double x,y,z;};
inline Point Projection(Point Light,Point_3D Object)//Object在Light下的投影
{return Light+((Vector){Object.x,Object.y}-Light)*(100/(100-Object.z));}

struct Line
{
    Point p;Vector v;double Ang;Line(){}
    Line(Point ps,Vector vs):p(ps),v(vs){Ang=atan2(v.y,v.x);}
    inline bool operator<(Line o){return Ang<o.Ang;}
};

Point_3D Mac[105];//机器坐标
Point Camera[5];//摄像头坐标

Point S[105];
std::vector<Point> Convex_Hull(std::vector<Point> p)//求凸包
{
    std::vector<Point> Ans;
    std::sort(p.begin(),p.end());
    int n=std::unique(p.begin(),p.end())-p.begin(),Sn=0;
    for(int i=0;i<=n-1;S[++Sn]=p[i++])
        while(Sn>=2&&Sign(Cross(p[i]-S[Sn-1],S[Sn]-S[Sn-1]))<0)--Sn;
    for(int i=1;i<Sn;++i)Ans.push_back(S[i]);
    Sn=0;
    for(int i=n-1;i>=0;S[++Sn]=p[i--])
        while(Sn>=2&&Sign(Cross(p[i]-S[Sn-1],S[Sn]-S[Sn-1]))<0)--Sn;
    for(int i=1;i<Sn;++i)Ans.push_back(S[i]);
    return Ans;
}

inline bool OnLeft(Point p,Line l){return Sign(Cross(p-l.p,l.v))==-1;}//点p是否在线l左侧
inline Point CrossP(Line A,Line B){return A.p+A.v*(Cross(B.v,A.p-B.p)/Cross(A.v,B.v));}//直线交点

Point P[305];
Line Q[305];
std::vector<Point> HPI(std::vector<Line> L)//半平面交
{
    std::sort(L.begin(),L.end());
    int n=L.size(),Qh=0,Qt=0;
    Q[0]=L[0];
    for(int i=1;i<n;++i)
    {
        while(Qh<Qt&&!OnLeft(P[Qt-1],L[i]))--Qt;
        while(Qh<Qt&&!OnLeft(P[Qh],L[i]))++Qh;
        if(Sign(Cross(L[i].v,Q[Qt].v)))Q[++Qt]=L[i];
        else if(OnLeft(L[i].p,Q[Qt]))Q[Qt]=L[i];
        if(Qh<Qt)P[Qt-1]=CrossP(Q[Qt-1],Q[Qt]);
    }
    while(Qh<Qt&&!OnLeft(P[Qt-1],Q[Qh]))--Qt;
    std::vector<Point> Ans;
    if(Qt-Qh<=1)return Ans;//没有公共区域
    P[Qt]=CrossP(Q[Qh],Q[Qt]);
    for(int i=Qh;i<=Qt;++i)Ans.push_back(P[i]);
    return Ans;
}

double Area(std::vector<Point> Poly)//求多边形面积
{
    double Sum=0;
    int n=Poly.size();
    for(int i=0;i<n;++i)Sum+=Cross(Poly[i],Poly[(i+1)%n]);
    return Sum/2;
}

int main()
{
    //freopen("in.txt","r",stdin);
    for(int n;~scanf("%d",&n);)
    {
        for(int i=1;i<=n;++i)scanf("%lf%lf%lf",&Mac[i].x,&Mac[i].y,&Mac[i].z);
        for(int i=1;i<=3;++i)scanf("%lf%lf",&Camera[i].x,&Camera[i].y);
        std::vector<Point> Shadow[4];
        std::vector<Line> Ls;
        for(int i=1;i<=3;++i)
        {
            for(int j=1;j<=n;++j)Shadow[i].push_back(Projection(Camera[i],Mac[j]));//投影到地面
            Shadow[i]=Convex_Hull(Shadow[i]);//求出凸包
            int Ss=Shadow[i].size();
            for(int j=0;j<Ss;++j)Ls.push_back((Line){Shadow[i][(j+1)%Ss],Shadow[i][j]-Shadow[i][(j+1)%Ss]});//转化位半平面交问题
        }
        Shadow[0]=HPI(Ls);
        printf("%.2f\n",Abs(Area(Shadow[0])));//面积取绝对值
    }
    return 0;
}

原文地址:https://www.cnblogs.com/LanrTabe/p/11254274.html

时间: 2024-11-07 11:00:29

[HDU4316]Mission Impossible(计算几何/凸包/半平面交)的相关文章

[模板] 计算几何2: 自适应Simpson/凸包/半平面交/旋转卡壳/闵可夫斯基和

//to update 一些基本的定义在这里: [模板] 计算几何1(基础): 点/向量/线/圆/多边形/其他运算 自适应Simpson 凸包 Andrew 算法, 即分别求上, 下凸包. 时间复杂度 \(O(n \log n)\). struct tvec{db x,y;}; il int dcmp(db a){return fabs(a)<=eps?0:(a>0?1:-1);} il db p2(db a){return a*a;} il db gougu1(db a,db b){retu

HDU 6617 Enveloping Convex(凸包+半平面交+二分)

首先对于这m个点维护出一个凸包M,那么问题就变成了判断凸包P进行放大缩小能不能包含凸包M.(凸包P可以进行中心对称变换再进行放大缩小,见题意) 如何判断合适的相似比呢,我们可以用二分去放大缩小凸包P的坐标,得到最小的相似比. 接下来就是如何判断是否包含.我们需要对凸包P上的每一条向量,在凸包M上找到这么一个点,使得这个点左侧的所有凸包M上的点都在向量的左侧,那么我们可以直接同时逆时针枚举,用一个变量维护凸包M上的点,因为是同逆时针,凸包M上的点至少有一个只会被遍历一次,那么复杂度可以证明为On,

HDU 3272 - Mission Impossible(计算几何)

HDU 3272 - Mission Impossible(计算几何) ACM 题目地址: HDU 3272 - Mission Impossible 题意: 在二维平面上,给你一个初始位置(hx,hy),你需要获得四种资源,A在x轴上任意位置,B在y轴上任意位置,C.D位置会告诉你.问获得四种资源后返回(hx,hy)最短要走多长. 分析: 三条线段与X.Y轴相交有三种情况: 与x,y都相交,此时最短距离为周长 仅与X或Y相交,这时枚举每条边,利用镜像对称算出距离,取最小值 与X和Y都不相交,这

【模板】凸包向内推进求不严格的半平面交——poj3384

想不明白这题写严格的半平面交为什么会错 /* 凸包所有边向内推进r */ #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<algorithm> #include<queue> using namespace std; #define N 205 typedef double db;

POJ 1474 Video Surveillance 半平面交求多边形是否有核

裸的半平面交求多边形是否有核. 多边形的核: 在多边形核上的点可以看到多边形的所有顶点,凸多边形的核显然就是多边形本身. 多边形的核是一个凸包,对多边形的所有边都做向着多边形的半平面交在判断一下是否构成凸包就可以了 一样的题目还有POJ3335 Video Surveillance Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3438   Accepted: 1523 Description A friend of y

「专题总结」半平面交(6/8completed)

还是题都没做完就来写一部分题解了,因为最近很忙(其实是效率太低),所以可能一时半会回不来这个专题. 为了防止什么都没剩下忘干净,于是乎瞎写个题解记录一下... 还是一如既往的不擅长集合. 刚开始我看到半平面交我还以为是用来解决三维计算几何问题的,吓一跳. 半平面不用多说,就是一条直线把一个二维平面分成两半,其中的一半. 半平面交其实很好理解,就是同一个二维平面中若干个半平面相交的部分. 维护的方法其实挺草率的,和凸包有不少互通的地方,只不过因为封闭所以是双端队列. 凸包偏向于点,半平面交偏向于线

LA 2218 (半平面交) Triathlon

题意: 有n个选手,铁人三项有连续的三段,对于每段场地选手i分别以vi, ui 和 wi匀速通过. 对于每个选手,问能否通过调整每种赛道的长度使得他成为冠军(不能并列). 分析: 粗一看,这不像一道计算几何的题目. 假设赛道总长度是1,第一段长x,第二段长y,第三段则是1-x-y 那么可以计算出每个选手完成比赛的时间Ti 对于选手i,若要成为冠军则有Ti < Tj (i ≠ j) 于是就有n-1个不等式,每个不等式都代表一个半平面. 在加上x>0, y>0, 1-x-y>0 这三个

POJ3525-Most Distant Point from the Sea(二分+半平面交)

Most Distant Point from the Sea Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3955   Accepted: 1847   Special Judge Description The main land of Japan called Honshu is an island surrounded by the sea. In such an island, it is natural t

UVALive 4992 Jungle Outpost(半平面交)

题意:给你n个塔(点)形成一个顺时针的凸包,敌人可以摧毁任何塔,摧毁后剩下的塔再组成凸包 在开始的凸包内选一点为主塔,保证敌人摧毁尽量多塔时主塔都还在现在的凸包内,求出最多摧毁的塔 题解:这题关键就是选的主塔在不同的地方,敌人就会摧毁不同的塔来让你的主塔暴露 因此这样想,找出敌人摧毁不同的塔后形成的所有不同的凸包,再求出所有凸包的交就好 具体就是,首先枚举摧毁塔的个数k,再把摧毁任意k个塔所形成的所有不同的凸包求一个交,如果为空就代表了摧毁k个塔一定可以保证无论主塔在哪儿都可以暴露(关键) 而所