hdu2948 简单计算几何 判断点在三角形 矩形 圆形内

题意

本质就是如标题说的计算几何。
两个人玩飞镖游戏,给出了一些形状的靶,每场比赛每个人投掷3次飞镖(Bob先手,Hannah后手),一个飞镖的得分为其在多少个靶上,最后输出获胜人的名字,平局输出Tied。
先给出一个数s代表靶的个数,之后s行代表靶。C代表圆形靶,给出圆心坐标和半径长度;R代表矩形靶,给出对角顶点的坐标x1 < x2 and y1 < y2;T代表三角形靶,给出三个点的坐标。
之后给出一个数n,代表n场比赛。每场比赛Bob投三次,给出坐标,Hannah投三次,给出坐标。
注意精度是1e-6

题解

直接模拟
判断点在圆形内:点和圆心的距离<=半径
判断点在矩形内:点坐标在对角顶点之间。即(x1<=x<=x2,y1<=y<=y2)
判断点在三角形内:点和三角形各边构成的三角形的面积==原三角形面积

刚开始学计算几何,代码变量函数名起的有点长,见谅。

#include 
using namespace std;
typedef long long ll;

const double eps = 1e-6;
const double PI = acos(-1);
const int maxn = 1e3+5;

struct Point{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y){}

    //向量+
    Point operator +(const Point &b)const
    {
        return Point(x+b.x,y+b.y);
    }
    //向量-
    Point operator -(const Point &b)const
    {
        return Point(x-b.x,y-b.y);
    }
    //点积
    double operator *(const Point &b)const
    {
        return x*b.x + y*b.y;
    }
    //叉积
    //P^Q>0,P在Q的顺时针方向;<0,P在Q的逆时针方向;=0,P,Q共线,可能同向或反向
    double operator ^(const Point &b)const
    {
        return x*b.y - b.x*y;
    }
};
typedef Point Vector;

struct Triangle{
    Point A,B,C;
}triangle[maxn];

struct Circle{
    Point O;
    double R;
}circle[maxn];

struct rectangle{
    Point A,B;
}rectangle[maxn];

//三态函数,判断两个double在eps精度下的大小关系
int dcmp(double x)
{
    if(fabs(x)return 0;
    else
        return x<0?-1:1;
}
//判断点P是否在三角形ABC中
bool InTriangle(Point A,Point B,Point C,Point P)
{
    double Sabc = fabs((B-A)^(C-A));
    double Spab = fabs((A-P)^(B-P));
    double Spac = fabs((A-P)^(C-P));
    double Spbc = fabs((B-P)^(C-P));
    return dcmp(Sabc-Spab-Spac-Spbc)==0;
}
//判断点P是否在O为圆心R为半径的圆上
bool InCircle(Point O,double R,Point P)
{
    double pr = sqrt(pow(P.x-O.x,2)+pow(P.y-O.y,2));
    return dcmp(pr-R)<=0;
}
//判断点P是否在A,B为对顶点的矩形上
bool InRectangle(Point A,Point B,Point P)
{
    return (dcmp(P.x-A.x)>=0&&dcmp(P.y-A.y)>=0&&dcmp(P.x-B.x)<=0&&dcmp(P.y-B.y)<=0);
}

int main()
{
    int t,triangle_num=0,circle_num=0,rectangle_num=0;
    char str[5];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",str);
        switch(str[0])
        {
        case 'C':
            scanf("%lf %lf %lf",&circle[circle_num].O.x,&circle[circle_num].O.y,&circle[circle_num].R);
            circle_num++;
            break;
        case 'R':
            scanf("%lf %lf %lf %lf",&rectangle[rectangle_num].A.x,&rectangle[rectangle_num].A.y,&rectangle[rectangle_num].B.x,&rectangle[rectangle_num].B.y);
            rectangle_num++;
            break;
        case 'T':
            scanf("%lf %lf %lf %lf %lf %lf",&triangle[triangle_num].A.x,&triangle[triangle_num].A.y,&triangle[triangle_num].B.x,&triangle[triangle_num].B.y,&triangle[triangle_num].C.x,&triangle[triangle_num].C.y);
            triangle_num++;
            break;
        }
    }
    scanf("%d",&t);
    while(t--)
    {
        int ans1=0,ans2=0;
        Point tmp;
        for(int i=1;i<=3;i++)
        {
            scanf("%lf %lf",&tmp.x,&tmp.y);
            for(int j=0;jif(InTriangle(triangle[j].A,triangle[j].B,triangle[j].C,tmp)) ans1++;
            for(int j=0;jif(InRectangle(rectangle[j].A,rectangle[j].B,tmp)) ans1++;
            for(int j=0;jif(InCircle(circle[j].O,circle[j].R,tmp)) ans1++;
        }
        for(int i=1;i<=3;i++)
        {
            scanf("%lf %lf",&tmp.x,&tmp.y);
            for(int j=0;jif(InTriangle(triangle[j].A,triangle[j].B,triangle[j].C,tmp)) ans2++;
            for(int j=0;jif(InRectangle(rectangle[j].A,rectangle[j].B,tmp)) ans2++;
            for(int j=0;jif(InCircle(circle[j].O,circle[j].R,tmp)) ans2++;
        }
        if(ans1==ans2) printf("Tied\n");
        else printf("%s\n",ans1"Hannah" : "Bob");
    }
    return 0;
}

你可能感兴趣的:(ACM,hdu,点定位)