Hdu 4458 Shoot the Airplane(判断点在多边形内)

58 篇文章 0 订阅
11 篇文章 0 订阅
该博客介绍了如何解决HDU 4458Shoot the Airplane问题,即在计算几何背景下判断子弹在给定时间内是否会处于多边形(飞机)内部。作者提出以飞机为参照系,考虑子弹的匀变速或匀速运动,并强调在处理精度要求高的情况下,应避免使用Dot产品来判断点是否在线段上,转而采用坐标差值的方法。
摘要由CSDN通过智能技术生成

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4458

思路:以飞机为参考系,则飞机相对静止,子弹加上水平方向速度-v。则只需枚举时间,判断该时间时点(子弹)是否在多边形(飞机)内。注意g可以为0,分匀变速和匀速。另外本题精度要求较高,判断点在线段上用坐标差值,避免使用Dot 。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debu
using namespace std;
const double eps = 1e-10;
const int maxn=25;
struct Point
{
    double x, y;
    Point(double x = 0, double y = 0) : x(x), y(y) {}
};
typedef Point Vector;
int n,v,b,g;
Point p[maxn];
Vector operator - (const Point &A, const Point &B)
{
    return Vector(A.x - B.x, A.y - B.y);
}
int dcmp(double x)
{
    if(fabs(x) < eps) return 0;
    else return x < 0 ? -1 : 1;
}
double Dot(const Vector &A, const Vector &B)
{
    return A.x * B.x + A.y * B.y;
}
double Cross(const Vector &A, const Vector B)
{
    return A.x * B.y - A.y * B.x;
}
bool OnSegment(const Point &p, const Point &a1, const Point &a2)
{
    //return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p)) < 0;
    if(dcmp(Cross(a1-p,a2-p))) return 0;
    else if(dcmp(p.x-min(a1.x,a2.x))>=0&&dcmp(p.x-max(a1.x,a2.x))<=0&&dcmp(p.y-min(a1.y,a2.y))>=0&&dcmp(p.y-max(a1.y,a2.y))<=0) return 1;
    else return 0;
}
int  isPointInPolygon(Point p, Point *poly, int n)
{
    int wn = 0;
    for(int i = 0; i < n; ++i)
    {
        if(OnSegment(p, poly[i], poly[(i+1)%n])) return 0;
        int k=dcmp(Cross(poly[(i+1)%n]-poly[i], p-poly[i]));
        int d1=dcmp(poly[i].y-p.y);
        int d2=dcmp(poly[(i+1)%n].y-p.y);
        if(k>0&&d1<=0&&d2>0) wn++;
        if(k<0&&d2<=0&&d1>0) wn--;
    }
    if(wn!=0)  return 1;
    else return 0;
}
int main()
{
#ifdef debug
    freopen("in.in","r",stdin);
#endif // debug
    while(scanf("%d%d%d",&v,&b,&g)==3)
    {
        if(v==0&&b==0&&g==0) break;
        scanf("%d",&n);
        double maxy=0.0;
        for(int i=0; i<n; i++)
        {
            scanf("%lf%lf",&p[i].x,&p[i].y);
            maxy=max(maxy,p[i].y);
        }
        int flag=0;
        double Time=dcmp(g)?(2.0*b/g):(1.0*maxy/b);
        //cout<<Time<<endl;
        for(double i=0.0; i<=Time; i+=0.001)
        {
            Point tmp;
            tmp.x=-v*i,tmp.y=b*i-0.5*g*i*i;
            if(isPointInPolygon(tmp,p,n))
            {
                printf("%.2f\n",i);
                flag=1;
                break;
            }
        }
        if(!flag) printf("Miss!\n");
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值