• 算法训练 Balloons in a Box (枚举,模拟)


    问题描述
      你要写一个程序,使得能够模拟在长方体的盒子里放置球形的气球。
      接下来是模拟的方案。假设你已知一个长方体的盒子和一个点集。每一个点代表一个可以放置气球的位置。在一个点上放置一个气球,就是以这个点为球心,然后让这个球膨胀,直到触及盒子的边缘或者一个之前已经被放置好的气球。你不能使用一个在盒子外面或者在一个之前已经放置好的气球里面的点。但是,你可以按你喜欢的任意顺序使用这些点,而且你不需要每个点都用。你的目标是按照某种顺序在盒子里放置气球,使得气球占据的总体积最大。
      你要做的是计算盒子里没被气球占据的体积。
    输入格式
      第一行包含一个整数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

    这道题主要学习了几何模拟方面的知识

    另外还学习了STL库中的next-permutation函数

    这个函数主要是求全排列用的

    详细讲解

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    
    using namespace std;
    const int maxn = 10;
    const double inf = 0x7ffffff;
    const double pi = acos(-1.0);
    
    struct point
    {
        double x,y,z;
        double r;
    }a[maxn], s, e;     //s和e是关于长方体的两个对点,a[]是关于长方体内的气球的位置
    int n;
    double ans;
    double dis(point p1, point p2)
    {
        double tmp1 = (p1.x - p2.x)*(p1.x - p2.x);
        double tmp2 = (p1.y - p2.y)*(p1.y - p2.y);
        double tmp3 = (p1.z - p2.z)*(p1.z - p2.z);
        return sqrt(tmp1+tmp2+tmp3);
    }
    
    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));
        double r = min(t1, t2);
        r = min(r, t3);
        return r;
    }
    
    double area(double r)       //求的面积
    {
        return 4.0*r*r*r*pi/3.0;
    }
    
    int main()
    {
        while(~scanf("%d", &n))
        {
            scanf("%lf %lf %lf", &s.x, &s.y, &s.z);
            scanf("%lf %lf %lf", &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));
            for(int i = 0; i < n; i++)
                scanf("%lf %lf %lf", &a[i].x, &a[i].y, &a[i].z);
            double ans = 0;
            int vis[maxn];
            for(int i = 0; i < n; i++)
                vis[i] = i;
    
            do
            {
                for(int i = 0; i < n; i++)
                    a[i].r = 0;
                double tmp = 0;
                for(int i = 0; i < n; i++)
                {
                    a[vis[i]].r = solve(vis[i]);
                    for(int j = 0; j < n; j++)
                    {
                        if(i == j || a[vis[j]].r == 0)
                            continue;
                        double tt = dis(a[vis[j]], a[vis[i]]) - a[vis[j]].r;
                        tt = max(tt, 0.0);
                        a[vis[i]].r = min(a[vis[i]].r, tt);
                    }
                    tmp += area(a[vis[i]].r);
                }
                ans = max(ans, tmp);
            }while(next_permutation(vis, vis+n));   //求出关于各个圆心位置的全排列
            printf("%.0f
    ", fabs(total-ans));      //关于next_permutation:http://bbs.csdn.net/topics/392058688
        }
        return 0;
    }
    View Code
    永远渴望,大智若愚(stay hungry, stay foolish)
  • 相关阅读:
    EF5+MVC4系列(5) 删除的方法 1:系统推荐的先查询后remove删除的方法 2:自己new一个包含主键的类,然后 attach附加 remove删除;3:使用db.Entry 修改状态删除4:EntityState的几种状态
    指定webapi 返回 json 格式 ; GlobalConfiguration.Configuration.Formatters.Clear()
    远程桌面连接工具 Remote Desktop Manager 9.1.2.0 Enterprise 多国语言绿色版附注册码 简单使用
    .NET WebAPI 正确抛出错误详细信息
    观察者模式 发布订阅者模式
    7月目标 socket , 一致性哈希算法 ; mongodb分片; 分布式消息队列; 中间件的使用场景
    在js中 把 json对象转化为String对象的方法
    mvc4中的 webapi 的使用方式
    Uncaught TypeError: TableInit is not a constructor
    Jquery复选框操作
  • 原文地址:https://www.cnblogs.com/h-hkai/p/8428458.html
Copyright © 2020-2023  润新知