Advertisement
Guest User

Dynamic Programming Solution to Floor Tilling Problem

a guest
Sep 1st, 2011
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.13 KB | None | 0 0
  1. """
  2. Anthony Theocharis' Example Solution to Floor Tiling
  3. """
  4.  
  5. import numpy
  6.  
  7. class Floor(object):
  8.     def __init__(self, width, height):
  9.         self.width = int(width)
  10.         self.height = int(height)
  11.  
  12. class TileSize(object):
  13.     def __init__(self, width, height):
  14.         self.width = int(width)
  15.         self.height = int(height)
  16.  
  17. def can_be_tiled(floor, tile_sizes):
  18.     """
  19.    Given a floor of a size (N, M) [width, height] and a list of tile sizes,
  20.    each with a unique width/height, determine if it is possible to cover the
  21.    entire floor using some inter number of each type of tile.
  22.  
  23.    This implementation assumes that the tiles can be rotated.
  24.  
  25.    Approach:
  26.        M = floor.height
  27.        N = floor.width
  28.        Any section is tileable if it can be broken into two subsections that
  29.        are themselves tileable. For each subsection size (i,j) determine if it
  30.        is tileable by finding two subsections that are tileable. Store the
  31.        results in the array R, and build R up from (0, 0) to (N, M).
  32.        A classic bottom-up dynamic programming / divide and conquer approach.
  33.  
  34.    Complexity:
  35.        O(N * M) memory
  36.        O(N * M * max(N, M)) steps
  37.    """
  38.  
  39.     # Store a byte-array representing the tile-ability of all sub-section sizes
  40.     # (really just needs to be a bit array, but that's hard in python)
  41.     R = numpy.zeros((floor.width+1, floor.height+1), dtype=numpy.int8)
  42.  
  43.     # Any section with width=0 or height=0 is already 'tiled'
  44.     R[:,0] = 1
  45.     R[0,:] = 1
  46.  
  47.     # Any section that is identical to a single tile is tileable by definition
  48.     for t in tile_sizes:
  49.         if t.width <= floor.width and t.height <= floor.height:
  50.             R[t.width][t.height] = 1
  51.  
  52.         if t.height <= floor.width and t.width <= floor.height:
  53.             R[t.height][t.width] = 1
  54.  
  55.     # Syntax Note:
  56.     # "for X in range(Y, Z+1):" is equivalent to
  57.     # "for (int X=Y; X<=Z; X++)" in C style languates.
  58.  
  59.     # For each size of floor (i, j), determine if it's tileable.
  60.     for i in range(1, floor.width+1):
  61.         for j in range(1, floor.height+1):
  62.  
  63.             # Try to find a horizontal split such that each section is tileable
  64.             if R[i][j] == 0:
  65.                 for a in range(0, (i/2)+1):
  66.                     if R[a][j] == R[i-a][j] == 1:
  67.                         R[i][j] = 1
  68.                         break
  69.  
  70.             # Try to find a vertical split such that each section is tileable
  71.             if R[i][j] == 0:
  72.                 for a in range(0, (j/2)+1):
  73.                     if R[i][a] == R[i][j-a] == 1:
  74.                         R[i][j] = 1
  75.                         break
  76.  
  77.             # Mark the rotation of this section as tileable, if appropriate
  78.             if R[i][j] == 1 and i <= floor.height and j <= floor.width:
  79.                 R[j][i] = 1
  80.  
  81.     if R[floor.width][floor.height] == 1:
  82.         return 'yes'
  83.     else:
  84.         return 'no'
  85.  
  86. if __name__ == '__main__':
  87.     print can_be_tiled(
  88.         Floor(5, 7),
  89.         [
  90.             TileSize(2, 3),
  91.             TileSize(3, 3),
  92.             TileSize(2, 4),
  93.             TileSize(5, 5),
  94.         ]
  95.     )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement