SRM507 DIV1 L2 [枚举+模拟]

CubePacking的题意是这样的,有Ns个1*1*1和Nb个L*L*L的立方体,对这些立方体打包,要求正交放置,问说最小用多大的长方体盒子,思路是枚举盒子,然后把东西往里放。

枚举就是要去除那些重复的项,即枚举满足x<=y<=z且x*y*z<=n的(x,y),这个的复杂度说是只有O(N^(2/3)),那样的话对于N是INT_MAX的话,也是可以接受的。然后放置那些立方体,求最小的高,复杂度是O(1),方法是让那些L*L*L的立方体组成长方体的样子贪心放置,然后剩下的填充进去。

比较难想到的是,要去枚举那个盒子,说是根据盒子的大小是有个上界这一条想到的。上述的算法复杂度平摊分析还不会,代码如下:

#include <iostream>
#include <string>
using namespace std;
 
typedef long long int64;
 
int getMinZ(int Ns, int Nb, int L, int x, int y)    //x <= y <= z
{
    if(x < L || y < L)  return INT_MAX;
    int nx = x / L, ny = y / L;
    int leftS = x * y - nx * ny * L * L;
    
    int h = (Nb + nx * ny - 1) / (nx * ny);
    int leftL = Nb % (nx * ny);
    if(leftL)  leftL = nx * ny - leftL;
    
    int leftM = Ns - leftL * L * L * L;
    leftM = max(leftM, 0);
    
    leftM -= leftS * h * L;
    leftM = max(leftM, 0);
    
    return (leftM + x * y - 1) / (x * y) + h * L;
}
 
int go(int Ns, int Nb, int L)
{
    int n = INT_MAX;
    int res = n;
    for(int x = 1; (int64)x * x * x <= n; x++)
    {
        for(int y = x; (int64)x * y * y <= n; y++)
        {
            int min_z = getMinZ(Ns, Nb, L, x, y);
            res = min((int64)res, (int64)x * y * min_z);
        }
    }
    return res;
}
 
class CubePacking
{
public:
    int getMinimumVolume(int Ns, int Nb, int L)
    {
        return go(Ns, Nb, L);
    }
};

你可能感兴趣的:(div)