A particular tiling of a square with rectangles

Suppose we have a square with side length S, and N copies of rectangular tile with length X and width Y. The program must show all the ways in which these copies can be arranged in a grid so that no two copies can touch each other .

By showing, I mean that it must show the set of coordinates of upper left corners of every copy in a grid.

I tried to do it in the following way:

  • Find a base case where I try to place every copy with 1 square separation. For example, for 6 copies of a 1x2 tile on a 6x6 grid, the base case is

    xx_xx_
    ______
    xx_xx_
    ______
    xx_xx_
    ______
    
  • Move the last tile to possible positions.

  • Return the last tile to the base case, move the tile before the last one to the possible position. Repeat Step 2.

  • Do it back for every tile.

  • Basically the problem is that I cannot find the cases where the difference in row or column numbers is 1 but they don't touch each other. For example, I cannot find this case:

    xx____  This tile
    ___xx_  and this one has a difference in row numbers 1.
    xx____
    ___xx_
    xx____
    ___xx_
    

    Can you suggest something? Or maybe a more efficient algorithm?

    NOTE: I try to implement it in Prolog.


    You'll find that the problem lends itself to constraint programming (which isn't that far from Prolog what you are trying to use):

  • given S,
  • you want a set of pairs A={(x,y)} where x elem {1..S} and y elem {1..S} and x and y denotes the top left corner of your tile,
  • such that for all (x,y) (x+1, y) is not in A and (x+2, y) is not in A and (x+3,y) is not in A and (x,y+1) is not in A ...more constraints, meaning that if you have a tile on (x,y) no tile 'starts' on (x+1,y) or (x+2,y) or (x+3,y) ie they don't overlap and don't touch.
  • The beauty is that with the above you declaratively specified the problem, and then your favourite constraint solver (I'd go with GECODE) goes and finds all solutions for you. And if your specification is not complete you get tiles which touch or overlap in unexpected ways, you can modify the specification and don't have to reinvent the wheel. This will work for quite large instances of the problem...when you can add clever ways of pruning the search tree, you only have to start inventing clever algorithms if you need large S. Sort of pay as you go.


    You can use a bitmask for the previous row each time you fill a specific row. For example:

    If previous row is like:

    XX----
    

    Then have a bitmask like 110000. To fill next row, see that you don't use the places where there are 1's in the bitmask.

    So you can do this:

    for(int i=0;i<(1<<S);i++)
     if(i & bitmask)
     {
     //can't place tile in this fashion as few tiles of previous row touch this row's tiles
     continue;
     }
     else
     {
     //No conflicts between rows, but with in this row there could be touching tiles as in 111100
     //Use a for loop to check if the given row has no two tiles touching
     //Check if each string of 1's is of length X
     //If all is well recursively call this function to fill the next row using i as the bitmask
     }
    

    I will let you figure out the actual implementation.

    链接地址: http://www.djcxy.com/p/40222.html

    上一篇: 算法挑战合并集合

    下一篇: 特殊的矩形矩形平铺