HDU3471 England vs Germany 计算几何题

Accepted3471296MS200K

对于速度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在平面法向量上的投影)的比值。

转载于:https://www.cnblogs.com/DreamUp/archive/2010/08/21/1805526.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值