Minimum exact cover of grid with squares; extra cuts

前端 未结 5 2049
迷失自我
迷失自我 2020-12-16 10:50

This problem appeared in a challenge, but since it is now closed it should be OK to ask about it.

The problem (not this question itself, this is just background info

5条回答
  •  北荒
    北荒 (楼主)
    2020-12-16 11:14

    I would use a search like A* to find a solution. It is important to note A* is like Greedy Best-First-Search in that it can use a heuristic to guide itself. Assuming you have a correct heuristic it will find near optimal (~0.95) solution in reasonable time.

    enter image description here

    Example solution uses 18 blocks instead of 19 as shown in example. In addition to heuristic you can use some precomputation to increase algorithm effectiveness. For example I computed what I call freedom gradient for each location. For example your initial map becomes a stage:

    enter image description here

    You can have your own heuristic that can be equally good or even better. I used this just because i found it was trivial. Stage numbers have following meaning: higher the number - more likely it will be in a big box (there are more constraints you can conclude, but it's a start).

    The stage value are sum total of 4 cellar automation rules.

    enter image description here

    For example top left

    cell(x,y) := min(cell(x,y-1) ?? 0, cell(x-1,y) ?? 0, cell(x-1,y-1) ?? 0) + 1
    

    The ?? operator is called the null-coalescing operator. It returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand.


    In addition you can cut computation work required by removing known solutions you got from precomputation and at each stage. In this case state 0:

    enter image description here

    Algorithm itself would repeat:

    1. Order cells and take highest
    2. Order automation rule results and take highest
    3. Find trivial cut offs

    enter image description here enter image description here


    If you want to get even faster results for larger grids then one fairly streight forward way would be to extend precomputation to compile templates. After that you can do template reduction.

    For example you could have a template (top left part)

    --+++
    +-+++
    +++++
    

    You can generate it's hash and add it to hashmap/dictionary with value 4 (meaning it will take minimum of 4 rectangles to cover +'s). Then you have 5x3 range with the same hash you know it is a trivial cut off with cost 4.

    Reason why this is faster is that comparisons take a lot of time compared to computing a hash that is near constant speed.


    Alternatively there is a way to hypnotize whether or what kind of solution we are actually looking for. Using Wolfram Mathematica function FindMinimum it would look something in the lines of:

    FindMinimum[{
      a + b + c + d + e + f + g, 
      (a 1^2 + b 2^2 + c 3^2 + d 4^2 + e 5^2 + f 6^2 + g 7^2) == 119 &&
      a >= 0 && b >= 0 && c >= 0 && d >= 0 && e >= 0 && f >= 0 && g >= 0 &&
      a \[Element] Integers &&
      b \[Element] Integers &&
      c \[Element] Integers &&
      d \[Element] Integers &&
      e \[Element] Integers &&
      f \[Element] Integers &&
      g \[Element] Integers
    }, {a,b,c,d,e,f,g}]
    

    This is based on assumption that we have 12x12 grid with 119 cells and it would give us an optimal solution with grid size counts used.

    Sadly wolfram alpha search engine does not interpret this, maybe in future.

提交回复
热议问题