Given a n by n board where n is of form 2k where k >= 1 (Basically n is a power of 2 with minimum value as 2). The board has one missing cell (of size 1 x 1). Fill the board using L shaped tiles. A L shaped tile is a 2 x 2 square with one cell of size 1×1 missing.
Figure 1: An example input
This problem can be solved using Divide and Conquer. Below is the recursive algorithm.
// n is size of given square, p is location of missing cell Tile(int n, Point p) 1) Base case: n = 2, A 2 x 2 square with one cell missing is nothing but a tile and can be filled with a single tile. 2) Place a L shaped tile at the center such that it does not cover the n/2 * n/2 subsquare that has a missing square. Now all four subsquares of size n/2 x n/2 have a missing cell (a cell that doesn't need to be filled). See figure 2 below. 3) Solve the problem recursively for following four. Let p1, p2, p3 and p4 be positions of the 4 missing cells in 4 squares. a) Tile(n/2, p1) b) Tile(n/2, p2) c) Tile(n/2, p3) d) Tile(n/2, p3)
The below diagrams show working of above algorithm
Figure 2: After placing the first tile
Figure 3: Recurring for the first subsquare.
Figure 4: Shows the first step in all four subsquares.
Examples:
Input : size = 2 and mark coordinates = (0, 0) Output : -1 1 1 1 Coordinate (0, 0) is marked. So, no tile is there. In the remaining three positions, a tile is placed with its number as 1. Input : size = 4 and mark coordinates = (0, 0) Output : -1 3 2 2 3 3 1 2 4 1 1 5 4 4 5 5
Below is the implementation of above idea:
// C++ program to place tiles #include <bits/stdc++.h> using namespace std;
int size_of_grid, b, a, cnt = 0;
int arr[128][128];
// Placing tile at the given coordinates void place( int x1, int y1, int x2,
int y2, int x3, int y3)
{ cnt++;
arr[x1][y1] = cnt;
arr[x2][y2] = cnt;
arr[x3][y3] = cnt;
} // Quadrant names // 1 2 // 3 4 // Function based on divide and conquer int tile( int n, int x, int y)
{ int r, c;
if (n == 2) {
cnt++;
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < n; j++) {
if (arr[x + i][y + j] == 0) {
arr[x + i][y + j] = cnt;
}
}
}
return 0;
}
// finding hole location
for ( int i = x; i < x + n; i++) {
for ( int j = y; j < y + n; j++) {
if (arr[i][j] != 0)
r = i, c = j;
}
}
// If missing tile is 1st quadrant
if (r < x + n / 2 && c < y + n / 2)
place(x + n / 2, y + (n / 2) - 1, x + n / 2,
y + n / 2, x + n / 2 - 1, y + n / 2);
// If missing Tile is in 3rd quadrant
else if (r >= x + n / 2 && c < y + n / 2)
place(x + (n / 2) - 1, y + (n / 2), x + (n / 2),
y + n / 2, x + (n / 2) - 1, y + (n / 2) - 1);
// If missing Tile is in 2nd quadrant
else if (r < x + n / 2 && c >= y + n / 2)
place(x + n / 2, y + (n / 2) - 1, x + n / 2,
y + n / 2, x + n / 2 - 1, y + n / 2 - 1);
// If missing Tile is in 4th quadrant
else if (r >= x + n / 2 && c >= y + n / 2)
place(x + (n / 2) - 1, y + (n / 2), x + (n / 2),
y + (n / 2) - 1, x + (n / 2) - 1,
y + (n / 2) - 1);
// dividing it again in 4 quadrants
tile(n / 2, x, y + n / 2);
tile(n / 2, x, y);
tile(n / 2, x + n / 2, y);
tile(n / 2, x + n / 2, y + n / 2);
return 0;
} // Driver program to test above function int main()
{ // size of box
size_of_grid = 8;
memset (arr, 0, sizeof (arr));
// Coordinates which will be marked
a = 0, b = 0;
// Here tile can not be placed
arr[a][b] = -1;
tile(size_of_grid, 0, 0);
// The grid is
for ( int i = 0; i < size_of_grid; i++) {
for ( int j = 0; j < size_of_grid; j++)
cout << arr[i][j] << " \t" ;
cout << "\n" ;
}
} |
// Java program to place tiles public class GFG
{ static int size_of_grid, b, a, cnt = 0 ;
static int [][] arr = new int [ 128 ][ 128 ];
// Placing tile at the given coordinates
static void place( int x1, int y1, int x2,
int y2, int x3, int y3)
{
cnt++;
arr[x1][y1] = cnt;
arr[x2][y2] = cnt;
arr[x3][y3] = cnt;
}
// Quadrant names
// 1 2
// 3 4
// Function based on divide and conquer
static int tile( int n, int x, int y)
{
int r = 0 , c = 0 ;
if (n == 2 )
{
cnt++;
for ( int i = 0 ; i < n; i++)
{
for ( int j = 0 ; j < n; j++)
{
if (arr[x + i][y + j] == 0 )
{
arr[x + i][y + j] = cnt;
}
}
}
return 0 ;
}
// finding hole location
for ( int i = x; i < x + n; i++)
{
for ( int j = y; j < y + n; j++)
{
if (arr[i][j] != 0 )
{
r = i;
c = j;
}
}
}
// If missing tile is 1st quadrant
if (r < x + n / 2 && c < y + n / 2 )
place(x + n / 2 , y + (n / 2 ) - 1 , x + n / 2 ,
y + n / 2 , x + n / 2 - 1 , y + n / 2 );
// If missing Tile is in 3rd quadrant
else if (r >= x + n / 2 && c < y + n / 2 )
place(x + (n / 2 ) - 1 , y + (n / 2 ), x + (n / 2 ),
y + n / 2 , x + (n / 2 ) - 1 , y + (n / 2 ) - 1 );
// If missing Tile is in 2nd quadrant
else if (r < x + n / 2 && c >= y + n / 2 )
place(x + n / 2 , y + (n / 2 ) - 1 , x + n / 2 ,
y + n / 2 , x + n / 2 - 1 , y + n / 2 - 1 );
// If missing Tile is in 4th quadrant
else if (r >= x + n / 2 && c >= y + n / 2 )
place(x + (n / 2 ) - 1 , y + (n / 2 ), x + (n / 2 ),
y + (n / 2 ) - 1 , x + (n / 2 ) - 1 ,
y + (n / 2 ) - 1 );
// dividing it again in 4 quadrants
tile(n / 2 , x, y + n / 2 );
tile(n / 2 , x, y);
tile(n / 2 , x + n / 2 , y);
tile(n / 2 , x + n / 2 , y + n / 2 );
return 0 ;
}
// Driver code
public static void main(String[] args)
{
// size of box
size_of_grid = 8 ;
// Coordinates which will be marked
a = 0 ; b = 0 ;
// Here tile can not be placed
arr[a][b] = - 1 ;
tile(size_of_grid, 0 , 0 );
// The grid is
for ( int i = 0 ; i < size_of_grid; i++)
{
for ( int j = 0 ; j < size_of_grid; j++)
System.out.print(arr[i][j] + " " );
System.out.println();;
}
}
} // This code is contributed by divyeshrabadiya07. |
// C# program to place tiles using System;
class GFG
{ static int size_of_grid, b, a, cnt = 0;
static int [,] arr = new int [128, 128];
// Placing tile at the given coordinates
static void place( int x1, int y1, int x2,
int y2, int x3, int y3)
{
cnt++;
arr[x1, y1] = cnt;
arr[x2, y2] = cnt;
arr[x3, y3] = cnt;
}
// Quadrant names
// 1 2
// 3 4
// Function based on divide and conquer
static int tile( int n, int x, int y)
{
int r = 0, c = 0;
if (n == 2)
{
cnt++;
for ( int i = 0; i < n; i++)
{
for ( int j = 0; j < n; j++)
{
if (arr[x + i, y + j] == 0)
{
arr[x + i, y + j] = cnt;
}
}
}
return 0;
}
// finding hole location
for ( int i = x; i < x + n; i++)
{
for ( int j = y; j < y + n; j++)
{
if (arr[i, j] != 0)
{
r = i;
c = j;
}
}
}
// If missing tile is 1st quadrant
if (r < x + n / 2 && c < y + n / 2)
place(x + n / 2, y + (n / 2) - 1, x + n / 2,
y + n / 2, x + n / 2 - 1, y + n / 2);
// If missing Tile is in 3rd quadrant
else if (r >= x + n / 2 && c < y + n / 2)
place(x + (n / 2) - 1, y + (n / 2), x + (n / 2),
y + n / 2, x + (n / 2) - 1, y + (n / 2) - 1);
// If missing Tile is in 2nd quadrant
else if (r < x + n / 2 && c >= y + n / 2)
place(x + n / 2, y + (n / 2) - 1, x + n / 2,
y + n / 2, x + n / 2 - 1, y + n / 2 - 1);
// If missing Tile is in 4th quadrant
else if (r >= x + n / 2 && c >= y + n / 2)
place(x + (n / 2) - 1, y + (n / 2), x + (n / 2),
y + (n / 2) - 1, x + (n / 2) - 1,
y + (n / 2) - 1);
// dividing it again in 4 quadrants
tile(n / 2, x, y + n / 2);
tile(n / 2, x, y);
tile(n / 2, x + n / 2, y);
tile(n / 2, x + n / 2, y + n / 2);
return 0;
}
// Driver code
static void Main()
{
// size of box
size_of_grid = 8;
// Coordinates which will be marked
a = 0; b = 0;
// Here tile can not be placed
arr[a, b] = -1;
tile(size_of_grid, 0, 0);
// The grid is
for ( int i = 0; i < size_of_grid; i++)
{
for ( int j = 0; j < size_of_grid; j++)
Console.Write(arr[i,j] + " " );
Console.WriteLine();
}
}
} // This code is contributed by divyesh072019. |
# Python3 program to place tiles size_of_grid = 0
b = 0
a = 0
cnt = 0
arr = [[ 0 for i in range ( 128 )] for j in range ( 128 )]
def place(x1, y1, x2, y2, x3, y3):
global cnt
cnt + = 1
arr[x1][y1] = cnt;
arr[x2][y2] = cnt;
arr[x3][y3] = cnt;
def tile(n, x, y):
global cnt
r = 0
c = 0
if (n = = 2 ):
cnt + = 1
for i in range (n):
for j in range (n):
if (arr[x + i][y + j] = = 0 ):
arr[x + i][y + j] = cnt
return 0 ;
for i in range (x, x + n):
for j in range (y, y + n):
if (arr[i][j] ! = 0 ):
r = i
c = j
if (r < x + n / 2 and c < y + n / 2 ):
place(x + int (n / 2 ), y + int (n / 2 ) - 1 , x + int (n / 2 ), y + int (n / 2 ), x + int (n / 2 ) - 1 , y + int (n / 2 ))
elif (r > = x + int (n / 2 ) and c < y + int (n / 2 )):
place(x + int (n / 2 ) - 1 , y + int (n / 2 ), x + int (n / 2 ), y + int (n / 2 ), x + int (n / 2 ) - 1 , y + int (n / 2 ) - 1 )
elif (r < x + int (n / 2 ) and c > = y + int (n / 2 )):
place(x + int (n / 2 ), y + int (n / 2 ) - 1 , x + int (n / 2 ), y + int (n / 2 ), x + int (n / 2 ) - 1 , y + int (n / 2 ) - 1 )
elif (r > = x + int (n / 2 ) and c > = y + int (n / 2 )):
place(x + int (n / 2 ) - 1 , y + int (n / 2 ), x + int (n / 2 ), y + int (n / 2 ) - 1 , x + int (n / 2 ) - 1 , y + int (n / 2 ) - 1 )
tile( int (n / 2 ), x, y + int (n / 2 ));
tile( int (n / 2 ), x, y);
tile( int (n / 2 ), x + int (n / 2 ), y);
tile( int (n / 2 ), x + int (n / 2 ), y + int (n / 2 ));
return 0
size_of_grid = 8
a = 0
b = 0
arr[a][b] = - 1
tile(size_of_grid, 0 , 0 )
for i in range (size_of_grid):
for j in range (size_of_grid):
print (arr[i][j], end = " " )
print ()
# This code is contributed by rag2127 |
<script> // Javascript program to place tiles var size_of_grid, b, a, cnt = 0;
var arr = Array.from(Array(128), ()=>Array(128).fill(0));
// Placing tile at the given coordinates function place(x1, y1, x2, y2, x3, y3)
{ cnt++;
arr[x1][y1] = cnt;
arr[x2][y2] = cnt;
arr[x3][y3] = cnt;
} // Quadrant names // 1 2 // 3 4 // Function based on divide and conquer function tile(n, x, y)
{ var r, c;
if (n == 2) {
cnt++;
for ( var i = 0; i < n; i++) {
for ( var j = 0; j < n; j++) {
if (arr[x + i][y + j] == 0) {
arr[x + i][y + j] = cnt;
}
}
}
return 0;
}
// finding hole location
for ( var i = x; i < x + n; i++) {
for ( var j = y; j < y + n; j++) {
if (arr[i][j] != 0)
r = i, c = j;
}
}
// If missing tile is 1st quadrant
if (r < x + n / 2 && c < y + n / 2)
place(x + n / 2, y + (n / 2) - 1, x + n / 2,
y + n / 2, x + n / 2 - 1, y + n / 2);
// If missing Tile is in 3rd quadrant
else if (r >= x + n / 2 && c < y + n / 2)
place(x + (n / 2) - 1, y + (n / 2), x + (n / 2),
y + n / 2, x + (n / 2) - 1, y + (n / 2) - 1);
// If missing Tile is in 2nd quadrant
else if (r < x + n / 2 && c >= y + n / 2)
place(x + n / 2, y + (n / 2) - 1, x + n / 2,
y + n / 2, x + n / 2 - 1, y + n / 2 - 1);
// If missing Tile is in 4th quadrant
else if (r >= x + n / 2 && c >= y + n / 2)
place(x + (n / 2) - 1, y + (n / 2), x + (n / 2),
y + (n / 2) - 1, x + (n / 2) - 1,
y + (n / 2) - 1);
// dividing it again in 4 quadrants
tile(n / 2, x, y + n / 2);
tile(n / 2, x, y);
tile(n / 2, x + n / 2, y);
tile(n / 2, x + n / 2, y + n / 2);
return 0;
} // Driver program to test above function // size of box size_of_grid = 8; // Coordinates which will be marked a = 0, b = 0; // Here tile can not be placed arr[a][b] = -1; tile(size_of_grid, 0, 0); // The grid is for ( var i = 0; i < size_of_grid; i++) {
for ( var j = 0; j < size_of_grid; j++)
document.write(arr[i][j] + " " );
document.write( "<br>" );
} // This code is contributed by rutvik_56. </script> |
-1 9 8 8 4 4 3 3 9 9 7 8 4 2 2 3 10 7 7 11 5 5 2 6 10 10 11 11 1 5 6 6 14 14 13 1 1 19 18 18 14 12 13 13 19 19 17 18 15 12 12 16 20 17 17 21 15 15 16 16 20 20 21 21
Time Complexity:
Recurrence relation for above recursive algorithm can be written as below. C is a constant.
T(n) = 4T(n/2) + C
The above recursion can be solved using Master Method and time complexity is O(n2)
Space Complexity: O(n)
How does this work?
The working of Divide and Conquer algorithm can be proved using Mathematical Induction. Let the input square be of size 2k x 2k where k >=1.
Base Case: We know that the problem can be solved for k = 1. We have a 2 x 2 square with one cell missing.
Induction Hypothesis: Let the problem can be solved for k-1.
Now we need to prove that the problem can be solved for k if it can be solved for k-1. For k, we put a L shaped tile in middle and we have four subsquares with dimension 2k-1 x 2k-1 as shown in figure 2 above. So if we can solve 4 subsquares, we can solve the complete square.
References:
http://www.comp.nus.edu.sg/~sanjay/cs3230/dandc.pdf