三维空间中有N个点,每个点可能是三种颜色的其中之一,三种颜色分别是红绿蓝,分别用’R’, ‘G’, ‘B’表示。
现在要找出三个点,并组成一个三角形,使得这个三角形的面积最大。
但是三角形必须满足:三个点的颜色要么全部相同,要么全部不同。
输入描述:
首先输入一个正整数N三维坐标系内的点的个数.(N <= 50)
接下来N行,每一行输入 c x y z,c为’R’, ‘G’, ‘B’ 的其中一个。x,y,z是该点的坐标。(坐标均是0到999之间的整数)
输出描述:
输出一个数表示最大的三角形面积,保留5位小数。
示例1
输入
5
R 0 0 0
R 0 4 0
R 0 0 3
G 92 14 7
G 12 16 8
输出
6.00000
方法一:向量叉乘。
整体思路是首先把输入的点按照颜色不同分别存放进3个动态数组,然后分两种情况计算面积,第一种是3个点颜色都相同的(又可以分为3种颜色的3种情况),第二种是3个点颜色都不相同的情况。最后比较所有计算的面积大小,选择最大的那个。
这里,计算面积的具体做法是向量叉乘法。s=axb/2,向量a和向量b分别用三角形的三个点的坐标表示,注意叉乘得到的结果应该是一个向量的模。
精度要求应该需要使用double型,向量坐标计算相乘时整数可能溢出,需要转换成long long 64位。
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
struct Point{
char c;
int x;
int y;
int z;
};
void run(int x1,int x2,int x3,int y1,int y2,int y3,int z1,int
z2,int z3,double &area){
long long x=(y2-y1)*(z3-z1)-(z2-z1)*(y3-y1);
long long y=(z2-z1)*(x3-x1)-(x2-x1)*(z3-z1);
long long z=(x2-x1)*(y3-y1)-(y2-y1)*(x3-x1);
double s=sqrt((x*x)+(y*y)+(z*z))*0.5;
area=max(area,s);
}
void calculate_area1(vector<Point>point,double &area){
for(int i=0;i<point.size();i++){
for(int j=i+1;j<point.size();j++){
for(int k=j+1;k<point.size();k++){
run(point[i].x,point[j].x,point[k].x,
point[i].y,point[j].y,point[k].y,
point[i].z,point[j].z,point[k].z,area);
}
}
}
}
void
calculate_area2(vector<Point>pointR,vector<Point>pointG,vector<Point>pointB,double
&area){
for(int i=0;i<pointR.size();i++){
for(int j=0;j<pointG.size();j++){
for(int k=0;k<pointB.size();k++){
run(pointR[i].x,pointG[j].x,pointB[k].x,
pointR[i].y,pointG[j].y,pointB[k].y,
pointR[i].z,pointG[j].z,pointB[k].z,area);
}
}
}
}
int main(){
int N;
cin>>N;
Point temp;
vector<Point>pointR;
vector<Point>pointG;
vector<Point>pointB;
for(int i=0;i<N;i++){
cin>>temp.c;
cin>>temp.x;
cin>>temp.y;
cin>>temp.z;
if(temp.c=='R') pointR.push_back(temp);
if(temp.c=='G') pointG.push_back(temp);
if(temp.c=='B') pointB.push_back(temp);
}
double area=0.0;
calculate_area1(pointR,area);
calculate_area1(pointG,area);
calculate_area1(pointB,area);
calculate_area2(pointR,pointG,pointB,area);
printf("%.5f",area);
return 0;
}
方法二:海伦公式。
#include<iostream>
#include <algorithm>
#include <math.h>
using namespace std;
/*
3
R 0 0 0
R 0 4 0
B 0 0 3
*/
struct node{
char c;
int x, y, z;
};
double MAX = 0;
int n;
vector<node> V;
//计算两点之间的距离
double L3(int i, int j){
return sqrt(double((V[i].x - V[j].x)*(V[i].x - V[j].x) + (V[i].y - V[j].y)*(V[i].y - V[j].y) + (V[i].z - V[j].z)*(V[i].z - V[j].z)));
}
//判断3个点是否能组成三角形
bool isSan(int i, int j, int k){
double a = L3(i, j);
double b = L3(i, k);
double c = L3(k, j);
if (a < (b + c) && b < (a + c) && c < (a + b))
{
return true;
}
return false;
}
//判断颜色是否相同或全不同
bool isColour(int i, int j, int k){
if (V[i].c == V[j].c && V[j].c == V[k].c)
{
return true;
}
else if (V[i].c != V[j].c &&V[i].c != V[k].c&&V[k].c != V[j].c)
{
return true;
}
return false;
}
//计算三角形面积(海伦公式)
double CmputeArea(int i, int j, int k){
double a = L3(i, j);
double b = L3(i, k);
double c = L3(k, j);
double p = (a + b + c) / 2;
return sqrt(p * (p - a) * (p - b) * (p - c));
}
//遍历所有可能的3个点
void run(){
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
for (int k = j + 1; k < n; k++)
{
if (isSan(i, j, k) && isColour(i, j, k))
{
double tArea = CmputeArea(i, j, k);
if (tArea > MAX)
{
MAX = tArea;
}
}
}
}
}
}
int main(){
cin >> n;
for (int i = 0; i < n; i++)
{
node t;
cin >> t.c >> t.x >> t.y >> t.z;
V.push_back(t);
}
run();
printf("%.5lf", MAX);
}