四点共面
给出三维空间上的四个点(点与点的位置均不相同),判断这4个点是否在同一个平面内(4点共线也算共面)。如果共面,输出”Yes”,否则输出”No”重点内容。
Input
第1行:一个数T,表示输入的测试数量(1 <= T <= 1000)
第2 - 4T + 1行:每行4行表示一组数据,每行3个数,x, y, z, 表示该点的位置坐标(-1000 <= x, y, z <= 1000)。
Output**
输出共T行,如果共面输出”Yes”,否则输出”No”。
Sample Input
1
1 2 0
2 3 0
4 0 0
0 0 0
Sample Output
Yes
该题的 思路 就是 根据 向量积 和 数量积 ,在这里 简单的 复习一下 所谓 向量积 的 就是 标题 所说的 两个 向量 的“X” 乘,其计算后的 结果 是得到 一个 与 前面 进行 运算的 两个 向量 所 确定的 平面的 一个 法向量; 所谓 数量积 就是 两个向量 的 对应 坐标 的乘积 的 和 ,计算结果 是一个 数,如果 两个 向量 垂直的话 ,那么 数量积 == 0. 所谓 混合积 呢 就是 向量积 和 数量积 的 综合 运算 。
下面 这个 代码 是 创建一个 结构是 结构体 里面的 代码 ,它的 作用是 重载 operator 后面的 那个一 “-”号 是 重载 相当于 是 要读取的 符号 ,这样说的 话 不太好理解 ,我举一个例子 : 对于 spot[1] - spot[2], 减号左右两边 都是 一个 结构体,我们知道 结构体 是可以 直接 进行 赋值的(spot[1] = spot[2]) 但是 不能 直接进行 加减乘除 等 运算, 那么 下面 那个 程序 就发挥啦 他神奇 的作用啦 ,我们 模拟一下 运算过程 下面 的 this 表示 spot[1] 然后 检测 到 spot[1] 后面的 是 减号“-”,然后可以 调用 下面的 重载 程序 把 spot[2] 当作 参数 传递 进来 变成啦 &o 然后 经过 运算之后 返回啦 一个 结构体 赋值给 啦 整个 表达式 “spot[1] - spot[2]”这个 表达式 就相当于 一个 结构体 变量 可以 进行 下面的 其他 运算 。
SPOT operator - (SPOT &o)
{
SPOT ans;
ans.x = this->x - o.x;
ans.y = this->y - o.y;
ans.z = this->z - o.z;
return ans;
}
如果 上面的 重载 代码 理解啦 现在 我们 再来 简单的 改变一下它的 功能 : 大家 猜一下 下面的结果 是不是一样?
// differ one 运算式 : spot[1] - spot[2]
SPOT operator - (SPOT &o)
{
SPOT ans;
ans.x = this->x + o.x;
ans.y = this->y + o.y;
ans.z = this->z + o.z;
return ans;
}
// differ two 运算式 : spot[1] + spot[2]
SPOT operator + (SPOT &o)
{
SPOT ans;
ans.x = this->x - o.x;
ans.y = this->y - o.y;
ans.z = this->z - o.z;
return ans;
}
第一个 表达式 实际上 是 进行啦 加法运算, 第二个 实际上 是进行啦 减法 运算 ,大家 是不是 明白啦 什么 呢?(~ ? ~)!!
对啦 大家 有可能 回想 &o 前面的 取值符 是干什么呢 ?其实 把 在这里 是没有用的 , 可以 去掉 ,其实 它的 作用 就是 把 进行运算的的结构体的 地址 传递过来 ,可以 对 传递进来的 结构体 的内容进行 改变。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <math.h>
using namespace std;
struct SPOT
{
double x;
double y;
double z;
SPOT operator - (SPOT &o)
{
SPOT ans;
ans.x = this->x - o.x;
ans.y = this->y - o.y;
ans.z = this->z - o.z;
return ans;
}
};
/**
* 计算 两个 空间 向量的 数量积
*/
double dot_product(const SPOT &a, const SPOT &b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}
/**
* 计算 两个 空间向量 的 向量 积
*/
SPOT cross_product(const SPOT &a, const SPOT &b)
{
SPOT ans;
ans.x = a.y * b.z - a.z * b.y;
ans.y = a.z * b.x - a.x * b.z;
ans.z = a.x * b.y - a.y * b.x;
return ans;
}
/**
* 主函数 的 整体 思路 大概 根据 就是 根据 三个 向量的 混合积 == 0 进行判断的
*/
int main()
{
int t;
SPOT spot[4];
while(scanf("%d", &t) != EOF)
{
while(t--)
{
for(int i = 0; i < 4; i++)
scanf("%lf%lf%lf", &spot[i].x, &spot[i].y, &spot[i].z);
double temp = dot_product(spot[3] - spot[0], cross_product(spot[2] - spot[0], spot[1] - spot[0]));
if(temp >= 0.0 && temp <= 1e-8)
printf("Yes\n");
else
printf("No\n");
}
}
return 0;
}