蓝桥杯练习4(balloon in box)

原创

首先记下一这个知识点:C语言程序中浮点数类型(%.2lf)编译器默认四舍五入,(最好自行测试一遍,可能不同平台使用的C语言版本不同,语言标准也有细微的区别。)如果不需要四舍五入,则要自行处理(浮点数{-5*10^{-x}},x=需要保留的小数位+1)。(已经写过测试代码进行了验证!!!)。另外,float精度是{2^{23}},能保证6位,double的精度是{2^{52}},能保证15位。

问题描述
  你要写一个程序,使得能够模拟在长方体的盒子里放置球形的气球。
  接下来是模拟的方案。假设你已知一个长方体的盒子和一个点集。每一个点代表一个可以放置气球的位置。在一个点上放置一个气球,就是以这个点为球心,然后让这个球膨胀,直到触及盒子的边缘或者一个之前已经被放置好的气球。你不能使用一个在盒子外面或者在一个之前已经放置好的气球里面的点。但是,你可以按你喜欢的任意顺序使用这些点,而且你不需要每个点都用。你的目标是按照某种顺序在盒子里放置气球,使得气球占据的总体积最大。
  你要做的是计算盒子里没被气球占据的体积。
输入格式
  第一行包含一个整数n表示集合里点的个数(1≤n≤6)。第二行包含三个整数表示盒子的一个角落的(x,y,z)坐标,第三行包含与之相对的那个角落的(x,y,z)坐标。接下来n行,每行包含三个整数,表示集合中每个点的(x,y,z)坐标。这个盒子的每维的长度都是非零的,而且它的边与坐标轴平行。
输出格式
  只有一行,为那个盒子没被气球占据的最小体积(四舍五入到整数)。
样例输入
2
0 0 0
10 10 10
3 3 3
7 7 7
样例输出
774
数据规模和约定
  所有坐标的绝对值小于等于1000
  对于20%的数据:n=1
  对于50%的数据:1≤n≤3
  对于100%的数据:1≤n≤6

分析:题意核心为限制箱子内点可作为气球中心,且气球膨胀只能相切于箱子或者其他气球的条件,得到空间利用最大化。
相切只需要满足最强条件即可,即最先到达的距离,分两种可能,一种是相切于箱子的6个面中的某一面,一种是相切于其他气球(由球心和半径确定)。
1.相切于6个面中的某一面只是基于比较球心到这六个面距离的比较。
2.相切于其他气球采用先入为主的策略(并且后面使用全排列,保证每一种情况都经过比较),只和已经确定下来的气球作比较。相切的情况一定能通过达到最小的两点间距离减去零一球半径得到。

你的目标是按照某种顺序在盒子里放置气球,使得气球占据的总体积最大。即枚举
每一种可能,记录最大值即可。

其中枚举可使用next_permutation()函数,其中变量为数组起始位置和结束位置(+1?),其包含在头文件<algorithm>中。

代码如下,简单枚举每种排列计算最优即可

//回宿舍改
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
const double pi=acos(-1.0);
using namespace std;
typedef struct vp
{
    double  x,y,z;
    double r;
}P;
P e,s,vv[20];
double l,w,h;
int n;
bool judge(double x,double y,double z)
{
    if(fabs(x-e.x)>l||fabs(x-s.x)>l)
        return true;
    if(fabs(y-e.y)>w||fabs(y-s.y)>w)
        return true;
//    if(fabs(x-e.z)>h||fabs(x-s.z)>h)
//     bug如上所示
if(fabs(z-e.z)>h||fabs(z-s.z)>h)
        return true;
    return false;

}
double mindis(double x,double y,double z)
{
    double t1=min(fabs(x-e.x),fabs(x-s.x));
    double t2=min(fabs(y-e.y),fabs(y-s.y));
    double t3=min(fabs(z-e.z),fabs(z-s.z));
    double p=min(t1,t2);
    double pp=min(t3,p);
    return pp;
}
double point_dis(P p1,P 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));
}
double area(double r)
{
    return r*r*r*pi*4/3.0;
}
int main()
{
    int a[10];

  while(cin>>n&&n>0)
{

cin>>e.x>>e.y>>e.z;
cin>>s.x>>s.y>>s.z;
l=fabs(e.x-s.x);
h=fabs(e.z-s.z);
w=fabs(e.y-s.y);
double total=l*h*w;
//cout<<total<<endl;
  for(int i=0;i<n;i++)
  {
      cin>>vv[i].x>>vv[i].y>>vv[i].z;
      a[i]=i;
  }
double maxx=0;
  do
  {
       double ini=0;
     for(int i=0;i<n;i++)
     {

         if(judge(vv[a[i]].x,vv[a[i]].y,vv[a[i]].z))
            continue;
            vv[a[i]].r=mindis(vv[a[i]].x,vv[a[i]].y,vv[a[i]].z);
         for(int j=0;j<i;j++)
         {
//             if(judge(vv[a[i]].x,vv[a[i]].y,vv[a[i]].z))
//            continue;
             double diss=point_dis(vv[a[i]],vv[a[j]])-vv[a[j]].r;
             if(diss<0)diss=0;
             vv[a[i]].r=min(vv[a[i]].r,diss);
        }
        ini+=area(vv[a[i]].r);
       // cout<<ini<<endl;
     }
   maxx=max(maxx,ini);
//     cout<<total<<endl<<ini<<endl;
//     cout<<vv[1].x<<"haha"<<vv[0].y<<endl;
  }while(next_permutation(a,a+n));
  //cout<<maxx<<endl;
  printf("%.0lf\n",total-maxx);
}


    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容