1100 - Paperweight

Your company makes artistic paperweights. Each paperweight is the union of two tetrahedra that share one face. They are clear solid glass with embedded colored flecks. One of the little flecks in each paperweight is actually a tiny RFID chip. This chip must be placed close to a partnered computer in order for that computer to operate. Typically this is accomplished by placing the paperweight on top of the computer. The chip has a limited range, however, so its distance from the flat computer top is significant. Therefore, it is important to calculate the minimum and maximum possible distances from the chip to the computer top when the paperweight is in a sufficiently stable position. A position is considered sufficiently stable if the paperweight would not move if the center of mass were somehow shifted up to 0.2 units in any direction. You may assume the paperweight has uniform density, and that the chip is small enough to be considered a point.

\epsfbox{p4795.eps}

As an example, consider a paperweight with the vertices of the common face at A = (0, 0, 0)B = (9, 0, 0),C = (0, 8, 0), the fourth vertex of one tetrahedron at D = (0, 0, 9), the fourth vertex of the other tetrahedron at E = (1, 1, - 8), and the chip at F = (1, 2, - 1). (See Figure 10, where the chip is shown as a red dot.) Placing the paperweight with face BCD on the computer results in the maximum distance of approximately 3.7 (upper part of Figure 11). Placing the paperweight with face ACD on the computer results in the minimum distance of 1.0 (lower part of Figure 11). Placing the paperweight with face ACE on the computer results in a distance of only 0.9 but is not sufficiently stable.

Input 

The input contains one or more test cases. Each test case is a single line describing the six points AB,CDE, and F, in that order. Each point is in turn described by three integers xy and z giving its coordinates. Both of the two tetrahedra have positive volume, D and E lie on opposite sides of the plane defined by the points ABC, and point F lies strictly inside the paperweight. Each coordinate is bounded by 1000 in absolute value. It is always possible to put the paperweight in at least one sufficiently stable position.

The input is terminated by a line containing only the integer 0.

Output 

For each test case, display the case number followed by the minimum and maximum distances from the chip to the base plane when the paperweight is sufficiently stable. These numbers should be rounded and displayed to five digits after the decimal point. Follow the format in the sample output.

Sample Input 

0 0 0 9 0 0 0 8 0 0 0 9 1 1 -8 1 2 -1 
0 0 0 7 0 0 0 7 0 0 0 7 -1 -2 -3 2 2 2 
1 2 3 6 2 3 -2 6 3 -1 0 7 4 1 -2 -1 5 3 
0

Sample Output 

Case 1: 1.00000 3.73526 
Case 2: 0.57735 2.66967 
Case 3: 0.28214 5.00871





#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<math.h>
#include<string>
#include<stdlib.h>
using namespace std;
#define PB push_back
double fabs(double num)
{
	return num<0?-num:num;
}

double fmin(double num1,double num2)
{
	return num1<=num2?num1:num2;
}

double fmax(double num1,double num2)
{
	return num1>=num2?num1:num2;
}

double Sqr(double num)
{
	return num*num;
}

struct Point
{
	double X;
	double Y;
	double Z;
};

bool operator ==(Point A,Point B)
{
	return (A.X==B.X&&A.Y==B.Y&&A.Z==B.Z);
}

Point MakePoint(double X0,double Y0,double Z0)
{
	Point Ret;
	Ret.X=X0;
	Ret.Y=Y0;
	Ret.Z=Z0;
	return Ret;
}

Point operator + (Point A,Point B)
{
	return MakePoint(A.X+B.X,A.Y+B.Y,A.Z+B.Z);
}

Point operator - (Point A,Point B)
{
	return MakePoint(A.X-B.X,A.Y-B.Y,A.Z-B.Z);
}

double operator * (Point A,Point B)
{
	return A.X*B.X + A.Y*B.Y + A.Z*B.Z;
}

Point operator ^ (Point A,Point B)
{
	return MakePoint(A.Y*B.Z-A.Z*B.Y, A.Z*B.X-A.X*B.Z, A.X*B.Y-A.Y*B.X);
}

Point operator * (Point A,double x)
{
	return MakePoint(A.X*x,A.Y*x,A.Z*x);
}

Point operator / (Point A,double x)
{
	return MakePoint(A.X/x,A.Y/x,A.Z/x);
}

double Volume(Point A,Point B,Point C,Point D)
{
	return fabs(((B-A)^(C-A))*(D-A))/6.000;
}

double Distance(Point A,Point B)
{
	return sqrt(Sqr(A.X-B.X) + Sqr(A.Y-B.Y) + Sqr(A.Z-B.Z));
}

double Abs(Point p)
{
	return sqrt(Sqr(p.X)+Sqr(p.Y)+Sqr(p.Z));
}

vector<Point> Flat;
Point A,B,C,D,E,F,G,G_ABCD,G_ABCE,P[10];
double V_ABCD,V_ABCE;

void FindCentre()
{
	V_ABCD=Volume(A,B,C,D);
	V_ABCE=Volume(A,B,C,E);

	G_ABCD=(A+B+C+D)/4.000;
	G_ABCE=(A+B+C+E)/4.000;
	G=G_ABCD+((G_ABCE-G_ABCD)*V_ABCE)/(V_ABCD+V_ABCE);
}

bool SameSide(Point p1,Point p2,Point p3)
{
	Point Nor=(p2-p1)^(p3-p1);
	bool plus=false,minus=false;
	for(int i=1;i<=5;i++)
	{
		if(P[i]==p1||P[i]==p2||P[i]==p3)
			continue;
		double temp=(P[i]-p1)*Nor;
		if(temp<0)
			minus=true;
		else if(temp>0)
			plus=true;
	}
	if(plus&&minus)
		return false;
	Flat.clear();
	Flat.push_back(p1);
	Flat.push_back(p2);
	Flat.push_back(p3);
	for(int i=1;i<=5;i++)
	{
		if(P[i]==p1||P[i]==p2||P[i]==p3)
			continue;
		double temp=(P[i]-p1)*Nor;
		if(temp==0)
			Flat.push_back(P[i]);
	}
	return true;
}

Point Shadow(Point p,Point p1,Point p2,Point p3)
{
	Point Nor=(p2-p1)^(p3-p1);
	Point Nor0=(Nor*(Nor*(p-p1))/Abs(Nor)/Abs(Nor));
	return (p-Nor0);
}

double ShadowHeight(Point p,Point p1,Point p2,Point p3)
{
	Point Nor=(p2-p1)^(p3-p1);
	return fabs(Nor*(p-p1)/Abs(Nor));
}

bool SameSide(Point A,Point B,Point C,Point P)
{
	Point AB=B-A;
	Point AC=C-A;
	Point AP=P-A;

	Point v1=AB^AC;
	Point v2=AB^AP;

	return (v1*v2)>=0;
}

bool PointinTriangle(Point A,Point B,Point C,Point P)
{
	return SameSide(A,B,C,P)&&SameSide(B,C,A,P)&&SameSide(C,A,B,P);
}

bool PointInArea(Point p)
{
	for(int i=0;i<Flat.size();i++)
		for(int j=i+1;j<Flat.size();j++)
			for(int k=j+1;k<Flat.size();k++)
				if(PointinTriangle(Flat[i],Flat[j],Flat[k],p))
					return true;
	return false;
}

double DistanceToLine(Point P,Point A,Point B)
{
	if((B-A)*(P-A)>0.000 && (A-B)*(P-B)>0.000)
		return sqrt(Sqr(Distance(A,P))-Sqr((B-A)*(P-A)/Abs((B-A))));
	return fmin(Distance(A,P),Distance(B,P));
}

bool Balance(Point p)
{
	if(!PointInArea(p))
		return false;
	for(int i=0;i<Flat.size();i++)
		for(int j=i+1;j<Flat.size();j++)
		{
			Point P_i=Flat[i],P_j=Flat[j];
			int k;
			for(k=0;k<Flat.size();k++)
				if(k!=i&&k!=j)
					break;
			Point P_k=Flat[k];
			bool plus=false,minus=false;
			Point Nor=(P_j-P_i)^(P_k-P_i)^(P_j-P_i);
			for(int l=0;l<Flat.size();l++) if(l!=i&&l!=j)
			{
				if(Nor*(Flat[l]-P_i)>0)
					plus=true;
				else if(Nor*(Flat[k]-P_i)<0)
					minus=true;
			}
			if(plus&&minus)
				continue;
			if(DistanceToLine(p,P_i,P_j)<0.2)
				return false;
		}
		return true;
}

void FindHull()
{
	double Min_Answer=2000.000,Max_Answer=0.000;
	P[1]=A;P[2]=B;P[3]=C;P[4]=D;P[5]=E;P[6]=F;
	for(int i=1;i<=5;i++)
		for(int j=i+1;j<=5;j++)
			for(int k=j+1;k<=5;k++)
			{
				if(SameSide(P[i],P[j],P[k]))
				{
					Point G0=Shadow(G,P[i],P[j],P[k]);
					if(Balance(G0))
					{
						Min_Answer=fmin(Min_Answer,ShadowHeight(F,P[i],P[j],P[k]));
						Max_Answer=fmax(Max_Answer,ShadowHeight(F,P[i],P[j],P[k]));
					}
				}
			}
	cout<<fixed<<Min_Answer<<" "<<Max_Answer<<"\n";
}

int main()
{
	cout.precision(5);
	int Case=0,deg;
	char ss[200];
	while(gets(ss))
	{
		if(strlen(ss)==1&&ss[0]=='0')
			break;
		scanf(ss,"%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
			&A.X,&A.Y,&A.Z,&B.X,&B.Y,&B.Z,
			&C.X,&C.Y,&C.Z,&D.X,&D.Y,&D.Z,
			&E.X,&E.Y,&E.Z,&F.X,&F.Y,&F.Z);
		cout<<"Case "<<++Case<<": ";
		FindCentre();
		FindHull();
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值