网格打包算法

时间:2012-05-11 15:00:12

标签: algorithm math fill

给定一个大小为w x h的矩形,并且需要在大小的矩形内容纳n大小相等的矩形,选择大小{{ 1}}和dx用于最佳填充原始矩形的较小矩形。

主要约束是所有数字必须是整数

我当前的(JS)算法是这样的:

dy

有更好的算法吗?

[注意:这不是作业 - 我试图解决如何画画的问题" n"画布上矩阵中的项目,但每个项目只能使用整个像素]。

2 个答案:

答案 0 :(得分:2)

看起来您基本上是在尝试计算GCD,您可以使用Euclidean algorithm有效地进行计算。我认为以下工作 - 尝试一下!

首先,计算gwn = GCD(w,n)和ghn = GCD(h,n)。如果其中任何一个是n,那么你就完成了 - 如果gwn = n,则意味着每个矩形可以是w / n×h像素。否则,如果h可以被n / gwn整除,或者w可以被n / ghn整除,则只能拟合矩形。

答案 1 :(得分:1)

function pick(tiles, grid_width, grid_height)
{
    var max_area = ~~(grid_width * grid_height / tiles);

    for (var area = max_area; area > 0; area--)
    {
        var result = [grid_width * grid_height - area * tiles];

        divisors_do(area,
            function (tile_width)
            {

                var tile_height = area / tile_width;
                if (tile_width > grid_width) return true;
                if (tile_height > grid_height) return true;

                var count_horizontal = ~~(grid_width / tile_width);
                var count_vertical = ~~(grid_height / tile_height);
                if (count_horizontal * count_vertical < tiles) return true;

                result.push([
                    tile_width, tile_height,
                    count_horizontal, count_vertical
                ]);
            });
        if (result.length > 1) return result;
    }
    return null;
}

function divisors_do(x, f)
{
    var history = [1];
    if (f(1) === false) return false;

    // for each prime factor
    return prime_factors_do(x,
        function(prime, primePower)
        {
            var len = history.length;

            for (var iHistory = 0; iHistory < len; iHistory++)
            {
                var divisor = history[iHistory];

                for (var power = 1; power <= primePower; power++)
                {
                    divisor *= prime;
                    history.push(divisor);

                    if (f(divisor) === false) return false;
                }
            }

            return true;
        });
}

function prime_factors_do(x, f)
{
    for (var test = 2; test*test <= x; test++)
    {
        var power = 0;
        while ((x % test) == 0)
        {
            power++;
            x /= test;
        }

        // If we found a prime factor, report it, and
        // abort if `f` returns false.
        if (power > 0 && f(test, power) === false)
            return false;
    }

    if (x > 1) return f(x,1);
    return true;
}

示例:

> pack(5, 12, 8);
[16, [2, 8, 6, 1], [4, 4, 3, 2]]
> pack(47,1024,768);
[16384, [64, 256, 16, 3], [128, 128, 8, 6], [256, 64, 4, 12], [512, 32, 2, 24]]

第一个示例产生两个等效结果:

  • 2x8瓷砖包装成一排6
  • 4x4瓷砖包装成两排3

在每种情况下,一个插槽未使用,总共16个单元未使用。

### ### ### ### ### . .    ####### ####### #######
### ### ### ### ###        ####### ####### #######
### ### ### ### ### . .    ####### ####### #######
### ### ### ### ###        ####### ####### #######
### ### ### ### ### . .    ####### ####### #######
### ### ### ### ###        ####### ####### #######
### ### ### ### ### . .    ####### ####### #######
### ### ### ### ###
### ### ### ### ### . .    ####### ####### .  .  .
### ### ### ### ###        ####### ####### 
### ### ### ### ### . .    ####### ####### .  .  .
### ### ### ### ###        ####### ####### 
### ### ### ### ### . .    ####### ####### .  .  .
### ### ### ### ###        ####### ####### 
### ### ### ### ### . .    ####### ####### .  .  .