题目链接
枚举每个点,算出可扩展的最大体积,就可求出剩余体积
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const double pi=acos(-1.0);
int n;
struct node{
double x,y,z,r;//坐标,半径
};
node a[10];//长方体内的气球的位置
node s,e;//关于长方体的两个对点
double ans;//答案
int vis[10];//记录点集
double v(double r)//返回球的体积
{
return 4.0*r*r*r*pi/3.0;
}
double solve(int i)//返回球心到长方体侧面的最短距离
{
double t1=min(fabs(a[i].x-e.x),fabs(a[i].x-s.x));
double t2=min(fabs(a[i].y-e.y),fabs(a[i].y-s.y));
double t3=min(fabs(a[i].z-e.z),fabs(a[i].z-s.z));
return min(t1,min(t2,t3));
}
double dis(node p1,node p2)//返回两点间的距离
{
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)+(p1.z-p2.z)*(p1.z-p2.z));
}
int main()
{
#ifdef local
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int ca=0;
while(scanf("%d",&n)&&n)
{
scanf("%lf%lf%lf%lf%lf%lf",&s.x,&s.y,&s.z,&e.x,&e.y,&e.z);
double total=fabs((s.x-e.x)*(s.y-e.y)*(s.z-e.z));//总体积
memset(a,0,sizeof(a));
int i,j;
ans=0;
for(i=0;i<n;i++)
scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].z);
for(i=0;i<n;i++)
vis[i]=i;//存储点集
do{
for(i=0;i<n;i++)
a[i].r=0;
double tmp=0;
for(i=0;i<n;i++)
{
a[vis[i]].r=solve(vis[i]);
for(j=0;j<n;j++)
{
if(i==j||a[vis[j]].r==0)continue;
double t=dis(a[vis[i]],a[vis[j]])-a[vis[j]].r;
t=max(t,0.0);
a[vis[i]].r=min(a[vis[i]].r,t);
}
tmp+=v(a[vis[i]].r);
}
ans=max(ans,tmp);
}while(next_permutation(vis,vis+n));//求出关于圆心各个位置的全排列
printf("Box %d: %0.f\n",++ca,fabs(total-ans));
puts("");
}
return 0;
}