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