现在的位置: 首页 > 综合 > 正文

HDU3471 England vs Germany 计算几何题

2012年12月12日 ⁄ 综合 ⁄ 共 2275字 ⁄ 字号 评论关闭
Accepted 3471 296MS 200K

对于速度V的方向有三种情况,可用V与ABCD面法向量的点积判断:
1 V指向ABCD面外侧,或V与ABCD面平行,不可能进球;
2 ball在ABCD面内侧,不可能进球;
3 ball在ABCD面上,当且仅当 P在多边形ABCD内(不包括边界)才进球
4 ball在ABCD面外侧,当且仅当 直线P+xV与ABCD面的交点Q在多边形ABCD内(不包括边界)才进球

代码

#include<iostream>
#include
<cmath>
using namespace std;
struct point{
double x,y,z;
point(
double xx=0,double yy=0,double zz=0){ //构造函数
x=xx,y=yy,z=zz;
}
point
operator *(double h){
return point(x*h,y*h,z*h);
}
double operator *(point h){ //点乘
return this->x*h.x+this->y*h.y+this->z*h.z;
}
point
operator +(point h){
return point(x+h.x,y+h.y,z+h.z);
}
point
operator -(point h){
return point(x-h.x,y-h.y,z-h.z);
}
//所有class method必须有匹配的左值类型进行调用而friend则无需这样
point friend operator %(point a,point b){ //叉乘
return point(a.y*b.z-b.y*a.z, a.z*b.x-b.z*a.x, a.x*b.y-b.x*a.y);
}
double len2(){
return x*x+y*y+z*z;
}
double len(){
return sqrt(len2());
}
void in(){
scanf(
"%lf%lf%lf",&x,&y,&z);
}
void show(){
printf(
"%.2lf %.2lf %.2lf\n",x,y,z);
}
}ball,v,a,b,c,d,e,f,g,h;
point dc,da,dh,aim;
//dh是dc和da的叉乘,也就是面abcd向外的法向量;
//aim是球最后飞到的位置,当然设置到无穷远处比较好的。

const double eps=1e-4;
int sign(double x){
if(fabs(x)<eps)return 0;
return x>0?1:-1;
}

point intersection(point l1,point l2,point s1,point s2,point s3)
//矢量与面的交点
{
point ret
=(s3-s2)%(s1-s2); //法向量
double t=ret*(s1-l1)/(ret*(l2-l1));
ret.x
=l1.x+(l2.x-l1.x)*t;
ret.y
=l1.y+(l2.y-l1.y)*t;
ret.z
=l1.z+(l2.z-l1.z)*t;
return ret;
}

double area(point a,point b,point c){ //三个点求面积
return ((b-a)%(c-a)).len()/2.0;
}
bool ok(point pcro){ //判断点是否位于矩形内
double s1,s2=0,tmp;
s1
=(b-a).len()*(d-a).len();
s2
=0;
tmp
=area(pcro,a,d);
s2
+=tmp;
if(sign(tmp)==0)
return false;
tmp
=area(pcro,d,c);
s2
+=tmp;
if(sign(tmp)==0)
return false;
tmp
=area(pcro,c,b);
s2
+=tmp;
if(sign(tmp)==0)
return false;
tmp
=area(pcro,b,a);
s2
+=tmp;
if(sign(tmp)==0)
return false;
if(sign(s1-s2)==0)
return true;
return false;
}

int main()
{
int cas,ca;
scanf(
"%d",&cas);
for(ca=1;ca<=cas;ca++)
{
ball.
in(); v.in();
a.
in(); b.in(); c.in(); d.in();
e.
in(); f.in(); g.in(); h.in();
dc
=c-d; da=a-d; dh=dc%da;//以d点作为参考点
aim=ball+v;
printf(
"Case %d: ",ca);
//不动球,平行了,或者飞出来的球,球在平面的另一侧,无效
if(sign(v.len()==0) || sign(v*dh)>=0 || ((ball-d)*dh)<0)
{
puts(
"Intelligent Larrionda!!!");
continue;
}
point pcro
=intersection(ball,aim,a,b,c);
puts(ok(pcro)
?"Stupid Larrionda!!!":"Intelligent Larrionda!!!");
}
return 0;
}

两点:

1.c++ operator定义为friend function请看博文http://blog.csdn.net/frankie110/archive/2009/12/30/5108373.aspx

2.当ball在ABCD面上时,intersection函数中的t等于0。 t代表的是什么?

  t代表的是(ball到平面的距离)与(v在平面法向量上的投影)的比值。

抱歉!评论已关闭.