431. 立方体
题目描述
已经知道一个正立方体的7个顶点的坐标,求最后顶点的坐标。
输入格式
第一行一个整数t,表示组数,t<1000。接下来每组数据有7行,每行三个整数,分别表示各点的x,y,z坐标,每个坐标的范围为[-1e6,1e6]。
输出格式
每组数据输出一行,所求顶点的坐标。
输入样例
2
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
0 3 0
4 0 0
7 4 0
3 7 0
4 0 5
7 4 5
0 3 5
输出样例
1 1 1
3 7 5
赛中提交:NULL
赛后AC:YES
题目大意:
给正方体的七个顶点坐标,求剩下一个点的坐标。
赛中的思路:
(1)求出所有点对其他点的距离的平方和,最小的肯定是缺失点的对角点
最大的是离缺失点最近的三个点
(2)以此标识出对角点和距离缺失点最近的三个点
(3)用距离缺失点最近的三个点到缺失点的距离相等来得出一个三元一次方程
用上高斯消元法的模板就可求出
但是这个想法其实比较复杂,而且高斯消元法又不熟且比较复杂
所以赛中连样例都没来得及过
赛后大神的思路:
(1)求出所有点对其他点的距离的平方和,最小的肯定是缺失点的对角点
次小的是离缺失点对角点最近的三个点
(2)以此标识出对角点和距离对角点最近的三个点
(3)求出三个向量,这三个向量加上对焦点的坐标就是缺失点的坐标
赛后WA原因:
有一个很大的收获
赛后还WA了好几次,原因很狗血
题目需要涉及到平方运算,一开始就注意到了存平方和的数组要用long long
但是还是一直没过,
最后把所有的数组都开成了long long就过了
原因是
求平方和的这个式子sum[i]+=((ll)(a[i][k]-a[j][k]))*((ll)(a[i][k]-a[j][k]));
如果没有先ll(long long)强制转换的话,
在做这个乘法时会把计算机暂时分配的一个存储结果的单元给爆掉
因为原来是int的所以他只会分配给一个int的单元
所以加了强制转换之后就果断过了
下面是ac代码
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <numeric>
#include <functional>
#define maxn 500005
using namespace std;
typedef long long ll;
int a[10][4];
ll sum[10],tmpsum[10];
int p[4][4];
int vec[4][4]={0};
int main()
{
int T;
scanf("%d",&T);
while(T--){
memset(a,0,sizeof(a));
memset(sum,0,sizeof(sum));
memset(tmpsum,0,sizeof(tmpsum));
memset(p,0,sizeof(p));
memset(vec,0,sizeof(vec));
for(int i=0;i<7;i+=1){
for(int j=0;j<3;j+=1){
scanf("%d",&a[i][j]);
}
}
for(int i=0;i<7;i+=1){
for(int j=0;j<7;j+=1){
if(j!=i){
for(int k=0;k<3;k+=1){
sum[i]+=((ll)(a[i][k]-a[j][k]))*((ll)(a[i][k]-a[j][k]));
}
}
}
tmpsum[i]=sum[i];
//printf("------%d\n",sum[i]);
}
//某个点到其他点的距离平方和,最小的肯定是缺失点的对角点
//次小的是离缺失点对角点最近的三个点,在下面排好序的tmpsum[1]中
sort(tmpsum,tmpsum+7);
int k=0;
for(int i=0;i<7;i+=1){
if(sum[i]==tmpsum[1]){
//如果是对角点最近点,就将其坐标复制给p
for(int j=0;j<3;j+=1){
p[k][j]=a[i][j];
}
//printf("eatshit %d\n",sum[i]);
k+=1;
}
else if(sum[i]==tmpsum[0]){
//对角点
//printf("haveshit %d\n",sum[i]);
for(int j=0;j<3;j+=1){
p[3][j]=a[i][j];
}
}
/*else{
printf("haveshit %d\n",sum[i]);
}*/
}
//求得对角点和离对角点最近的三个点的坐标
for(int i=0;i<3;i+=1){
for(int j=0;j<3;j+=1){
vec[i][j]=p[i][j]-p[3][j];
}
vec[3][i]=p[3][i];
}
for(int i=0;i<3;i+=1){
for(int j=0;j<3;j+=1){
vec[3][j]+=vec[i][j];
}
}
printf("%d %d %d\n",vec[3][0],vec[3][1],vec[3][2]);
}
return 0;
}