记圆心为(x0, y0, z0)。
容易想到,计算长方体上离圆心最近一点(x', y', z')到圆心的距离dismin就可以判断出YES和NO。
由于“长方体的每条边和坐标轴平行”(这个条件非常重要),可以知道长方体上任意一点左边(x, y, z)满足xmin<=x<=xmax, y,z相同。而xmin, xmax等可以直接由长方体的八个顶点坐标得到。
从dismin^2=(x0-x)^2+(y0-y)^2+(z0-z)^2可以知道,要找到(x', y', z')这一点,其实xyz三个那种歌方向上是完全独立的,分别在xmin<=x<=xmax, ymin<=y<=ymax, zmin<=z<=zmax中间选取合适的x, y, z使(x0-x)^2、(y0-y)^2和(z0-z)^2都最小就可以了。
2 0 0 0 0 0 1 0 1 0 1 0 0 1 1 0 1 0 1 0 1 1 1 1 1 2 2 2 2 0 0 0 0 0 1 0 1 0 1 0 0 1 1 0 1 0 1 0 1 1 1 1 1 2 2 2 1
Yes No
#include <cstdio> #include <cmath> using namespace std; struct point { double x,y,z; }; int main() { int n,i; double xmin,xmax,ymin,ymax,zmin,zmax,xx,yy,zz,r; point points[10],ball; scanf("%d",&n); while(n--) { for(i=0;i<8;i++) scanf("%lf%lf%lf",&points[i].x,&points[i].y,&points[i].z); scanf("%lf%lf%lf%lf",&ball.x,&ball.y,&ball.z,&r); xmin=ymin=zmin=1000000;xmax=ymax=zmax=-1; for(i=0;i<8;i++) { if(xmin>points[i].x) xmin=points[i].x; if(xmax<points[i].x) xmax=points[i].x; if(ymin>points[i].y) ymin=points[i].y; if(ymax<points[i].y) ymax=points[i].y; if(zmin>points[i].z) zmin=points[i].z; if(zmax<points[i].z) zmax=points[i].z; } if(ball.x<xmin) xx=xmin; else if(ball.x>xmax) xx=xmax; else xx=ball.x; if(ball.y<ymin) yy=ymin; else if(ball.y>ymax) yy=ymax; else yy=ball.y; if(ball.z<xmin) zz=zmin; else if(ball.z>zmax) zz=zmax; else zz=ball.z; double diss=sqrt((xx-ball.x)*(xx-ball.x)+(yy-ball.y)*(yy-ball.y)+(zz-ball.z)*(zz-ball.z)); if(diss>r) printf("No\n"); else printf("Yes\n"); } return 0; }