题意:大概意思是地球和其他星球要建立通信,但是发出的信号是一条三维空间的直线,求想要让地球和其他所有星球都建立通信最少需要发射几次信号。
思路:把问题抽象出来就是求三维坐标系下经过地球的那个点以及其他星球所在的点最少能画成几条直线,即判断哪些点是共线的就行。
我的思路是把地球所在的点视为坐标系原点,再把其他星球坐标的符号化为一致,x、y、z坐标分别都除以三者的最大公约数,化为最简。若两个星球坐标化为最简后是一样的,则这两个星球坐标和地球必定共线。
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<stack>
#include<queue>
#include<utility>
#include<vector>
#include<cmath>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
struct Point{
int x, y, z;
Point(){}
Point(int a, int b, int c){x = a; y = b; z = c;}
bool operator == (Point& tmp){
return x==tmp.x && y==tmp.y && z==tmp.z;
}
};
int n;
int ex, ey, ez;
Point p[5010];
int tot;
int GetGcd2(int a, int b)
{
if(a < b) swap(a, b);
return b==0? a:GetGcd2(b, a%b);
}
int GetGcd3(int x, int y, int z)
{
return GetGcd2(GetGcd2(x, y), z);
}
int main()
{
while(scanf("%d", &n) == 1){
tot = 0;
scanf("%d%d%d", &ex, &ey, &ez);
int x, y, z;
for(int i=1; i<n; i++){
scanf("%d%d%d", &x, &y, &z);
x -= ex; //化为以地球为坐标系原点的坐标
y -= ey;
z -= ez;
if(x < 0){ //将符号化为一致
x = -x;
y = -y;
z = -z;
}
else if(x == 0){
if(y < 0){
y = -y;
z = -z;
}
else if(y == 0){
if(z < 0){
z = -z;
}
}
}
int gcd = GetGcd3(abs(x), abs(y), abs(z)); //x、y、z分别处以三者的最大公约数
x = x/gcd;
y = y/gcd;
z = z/gcd;
if(i == 1){
p[tot++] = Point(x, y, z);
}
else{
bool ok = true;
Point tmp(x, y, z);
for(int j=0; j<tot; j++){
if(p[j] == tmp){
ok = false;
break;
}
}
if(ok){
p[tot++] = tmp;
}
}
}
printf("%d\n", tot);
}
return 0;
}