将较小的矩形组合成较大的矩形

时间:2011-11-07 11:40:38

标签: algorithm

我有一个问题,我需要将小方块合并为更大的矩形。假设我有一个2D网格,填充随机1和0:

1 0 1 1 0
1 0 1 1 1
0 1 0 1 1
0 1 0 1 1
0 0 1 0 0

1表示已填充的区域,我将它们绘制成屏幕方式为正方形。但是,对于这个问题,我需要先将它们匹配成矩形。在示例节目中,左上角的1​​是>

1
1

可以加入矩形。

我认为这应该足以解释我的需要。然而,优选的是,不在一个以上的矩形中使用特定的正方形。此外,它不一定是具有最少数量矩形的最佳情况,只是具有较少矩形的更好情况。如果它会使事情变得容易,也允许1x1矩形。

任何有关我可以从哪里开始,甚至解决方案的见解都将受到赞赏。

如果你想知道这个问题背后的原因,我正在为我正在研究的游戏开发一个关卡构建器,我希望减少我的顶点数。我以为我会从方块开始,因为它们会很简单,但即使这样也让我难以置信。

感谢您花时间阅读!

2 个答案:

答案 0 :(得分:2)

一种简单的方法是寻找相邻的正方形并将它们变成矩形。要做到这一点,首先水平穿过网格并水平相邻的方块连接在一起,然后垂直穿过网格并垂直连接正方形。

考虑:

H =水平矩形

V =垂直矩形

你原来的例子:

 1 0 1 1 0
 1 0 1 1 1
 0 1 0 1 1
 0 1 0 1 1
 0 0 1 0 0

会变成:

V 0 H H 0
V 0 H H H
0 V 0 H H
0 V 0 H H
0 0 1 0 0

这种方法不是最优的,但如果可以在给定2D网格的情况下这样做,它会将方块变成矩形。

答案 1 :(得分:1)

我正在使用两个步骤来减少游戏中的碰撞器数量。合并水平连续类型,然后合并具有相同宽度的垂直类型。

steps

代码是一项正在进行的工作,但它似乎正在运作〜

public class Tiles
{
    public char Type { get; set; }
    public int X { get; set; }
    public int Y { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }

    public override string ToString()
    {
        return $@"({X}, {Y}, {Width}, {Height}) '{Type}'";
    }
}

public class TilesFromStrings
{
    private List<Tiles> Result = new List<Tiles>();

    public IEnumerable<Tiles> Create(params string[] lines)
    {
        Result.Clear();

        CreateMergedHorizontalTiles(lines);
        MergeVerticallyTilesWithSameWidth();

        return Result.Where(f => f.Height > 0);
    }

    private void MergeVerticallyTilesWithSameWidth()
    {
        foreach (var current in Result)
        {
            foreach (var other in Result)
            {
                if (other.Y + other.Height == current.Y
                        && other.X == current.X
                        && other.Height > 0
                        && current.Height > 0)
                {
                    if (other.Type == current.Type)
                    {
                        if (other.Width == current.Width)
                        {
                            current.Height--;
                            current.Y++;
                            other.Height++;
                            break;
                        }
                    }
                }
            }
        }
    }

    private void CreateMergedHorizontalTiles(string[] tiles)
    {
        Tiles currentRect = null;
        var lastColumnIndex = tiles[0].Length - 1;
        for (int rowIndex = 0; rowIndex < tiles.Length; rowIndex++)
        {
            for (int columnIndex = 0; columnIndex < tiles[rowIndex].Length; columnIndex++)
            {
                var currentType = tiles[rowIndex][columnIndex];

                if (columnIndex == 0)
                {
                    currentRect = new Tiles
                    {
                        X = columnIndex + 1,
                        Y = rowIndex + 1,
                        Width = 1,
                        Height = 1,
                        Type = currentType
                    };

                    continue;
                }

                if (columnIndex == lastColumnIndex)
                {
                    if (currentRect.Type == currentType)
                    {
                        Result.Add(currentRect);
                        currentRect.Width++;
                    }
                    else
                    {
                        Result.Add(currentRect);
                        currentRect = new Tiles
                        {
                            X = columnIndex + 1,
                            Y = rowIndex + 1,
                            Width = 1,
                            Height = 1,
                            Type = currentType
                        };
                        Result.Add(currentRect);
                    }

                    continue;
                }

                if (currentRect.Type == currentType)
                {
                    currentRect.Width++;
                }
                else
                {
                    Result.Add(currentRect);
                    currentRect = new Tiles
                    {
                        X = columnIndex + 1,
                        Y = rowIndex + 1,
                        Width = 1,
                        Height = 1,
                        Type = currentType
                    };
                }
            }
        }
    }
}