[英]How do I solve this tromino tiling problem?
我正在尝试为 nxn 板解决这个 tromino 平铺问题。 鉴于 nxn 板中缺少正方形坐标 (MS) x 和 y,我们必须用“L”形瓷砖填充板的其余部分。
我设法获得了 2 x 2 板的输出。 但是,我坚持使用 4 x 4、8 x 8 等电路板尺寸的输出。
以下是我编写的递归调用自身以打印板的函数:
/* This program tiles with right trominoes an nxn
board with one square missing, assuming that n
is a power of 2. */
#include <stdio.h>
#include <stdlib.h>
// #define LR 0
// #define LL 1
// #define UR 3
// #define UL 2
// #define MS -1
const int Max = 256;
int board[Max][Max];
void tromino /* function to do tiling */
( int x_board, /* x coordinate of board */
int y_board, /* y coordinate of board */
int x_missing, /* x coordinate of missing square */
int y_missing, /* y coordinate of missing square */
int board_size); /* size of board */
void show_Tromino(int size, int x_miss, int y_miss);
int main()
{
int board_size,
x_missing, /* x coordinate of missing square */
y_missing; /* y coordinate of missing square */
do {
printf( "\n-------------------------------------" );
printf( "\nEnter size of board (0 to quit): " );
scanf( "%d", &board_size );
if ( board_size ) {
printf( "\nEnter coordinates of missing square: " );
scanf( "%d%d", &x_missing, &y_missing );
printf( "\n\nTiling\n" );
// if(board[x_board][0] == x_missing && board[0][y_board] == y_missing)
// printf("MS\t");
//board[x_missing][y_missing] = -1;
tromino( 0, 0, x_missing, y_missing, board_size);
show_Tromino(board_size, x_missing, y_missing);
}
} while ( board_size );
return EXIT_SUCCESS;
}
void tromino( int x_board, /* x coordinate of board */
int y_board, /* y coordinate of board */
int x_missing, /* x coordinate of missing square */
int y_missing, /* y coordinate of missing square */
int board_size) /* size of board */
{
int half_size = board_size/2, /* size of subboard */
x_center, /* x coordinate of center of board */
y_center, /* y coordinate of center of board */
x_upper_left, /* x coordinate of missing square in upper
left subboard */
y_upper_left, /* y coordinate of missing square in upper
left subboard */
x_upper_right, /* x coordinate of missing square in upper
right subboard */
y_upper_right, /* y coordinate of missing square in upper
right subboard */
x_lower_right, /* x coordinate of missing square in lower
right subboard */
y_lower_right, /* y coordinate of missing square in lower
right subboard */
x_lower_left, /* x coordinate of missing square in lower
left subboard */
y_lower_left; /* y coordinate of missing square in lower
left subboard */
if ( board_size == 2 ) /* 2x2 board */
{
for(int i=board_size-1; i>=0; i--)
{
for(int j=0;j<board_size;j++)
{
if(i==x_missing && j==y_missing)
//printf("MS\t");
{ board[i][j] = -1;}
//printf( "%d %d ", x_board + 1, y_board + 1 );
/* find and print orientation of tromino */
if(x_missing == x_board)
{
if(y_missing == y_board)
// printf("UR\t");
{board[i][j] = 2;}
else
// printf("LR\t");
{board[i][j] = 0;}
}
else
{
if(y_missing == y_board)
// printf("UL\t");
{board[i][j] = 3;}
else
// printf("LL\t");
{board[i][j] = 1;}
}
}
printf("\n");
}
return;
}
// if(board_size>2)
// { /* compute x and y coordinates of center of board */
x_center = x_board + half_size;
y_center = y_board + half_size;
if((x_missing < x_center) && (y_missing < y_center))
{
//printf("UR\t");
x_upper_left = x_center - 1;
y_upper_left = y_center;
x_upper_right = x_center;
y_upper_right = y_center;
x_lower_left = x_missing;
y_lower_left = y_missing;
x_lower_right = x_center;
y_lower_right = y_center - 1;
}
if((x_missing >= x_center) && (y_missing < y_center))
{
//printf("UL\t");
x_upper_left = x_center - 1;
y_upper_left = y_center;
x_upper_right = x_center;
y_upper_right = y_center;
x_lower_left = x_center - 1;
y_lower_left = y_center - 1;
x_lower_right = x_missing;
y_lower_right = y_missing;
}
if((x_missing >= x_center) && (y_missing >= y_center))
{
//printf("LL\t");
x_upper_left = x_center - 1;
y_upper_left = y_center;
x_upper_right = x_missing;
y_upper_right = y_missing;
x_lower_left = x_center - 1;
y_lower_left = y_center - 1;
x_lower_right = x_center;
y_lower_right = y_center - 1;
}
if((x_missing < x_center) && (y_missing >= y_center))
{
//printf("LR\t");
x_upper_left = x_missing;
y_upper_left = y_missing;
x_upper_right = x_center;
y_upper_right = y_center;
x_lower_left = x_center - 1;
y_lower_left = y_center - 1;
x_lower_right = x_center;
y_lower_right = y_center - 1;
}
/* tile the four subboards */
tromino( x_board, y_board + half_size,
x_upper_left, y_upper_left, half_size);
tromino( x_board + half_size, y_board + half_size,
x_upper_right, y_upper_right, half_size);
tromino( x_board + half_size, y_board,
x_lower_right, y_lower_right, half_size);
tromino( x_board, y_board,
x_lower_left, y_lower_left, half_size);
}
void show_Tromino(int size, int x_miss, int y_miss)
{
int bsize[Max][Max];
for(int i=size-1; i>=0;i--)
{
for(int j=0; j<size;j++)
{
if(!(bsize[i][j] == -1 || (j==x_miss && i==y_miss)))
{
if(bsize[i][j] == 1)
{
printf("LL\t");
}
else if(bsize[i][j] == 2)
{
printf("UL\t");
}
else if(bsize[i][j] == 3)
{
printf("UR\t");
}
else if(bsize[i][j] == 0)
{
printf("LR\t");
}
}
else if (bsize[i][j] == -1 || (j==x_miss && i==y_miss))
{
printf("MS\t");
}
bsize[i][j] += 1;
}
printf("\n");
}
}
output1 : 当电路板尺寸为 2 x 2 时(这是正确的)
Enter size of board (0 to quit): 2
Enter coordinates of missing square: 0 1
Tiling
------
MS LR
LR LR
output2 :当电路板尺寸为 4 x 4(这是不正确的)时。 不过,我得到了 Missing Square(MS) 的正确位置。
Enter size of board (0 to quit): 4
Enter coordinates of missing square: 0 1
Tiling
------
LR LR LR LR
LR LR LR LR
MS LR LR LR
LR LR LR LR
output2 :当电路板尺寸为 4 x 4(这是预期的)时
Enter size of board (0 to quit): 4
Enter coordinates of missing square: 0 1
Tiling
------
UL UL UR UR
UL UR UR UR
MS LR UR LR
LR LR LR LR
笔记:
问题是由于基本情况。 在求解 2x2 时,您忘记考虑偏移。 每次只更新[0,0],[0,1],[1,0],[1,1]。 其余的值(除了丢失的图块)都是垃圾值。
我相信您的编译器默认将所有数组值设置为零。 所以垃圾值导致值LR。
编辑:添加了更正的代码。 只需将输出映射到字母(我已经打印了数字)
/* This program tiles with right trominoes an nxn
board with one square missing, assuming that n
is a power of 2. */
#include <stdio.h>
#include <stdlib.h>
// #define LR 4
// #define LL 1
// #define UR 3
// #define UL 2
// #define MS -1
# define Max 256
int board[Max][Max];
void tromino /* function to do tiling */
( int x_board, /* x coordinate of board */
int y_board, /* y coordinate of board */
int x_missing, /* x coordinate of missing square */
int y_missing, /* y coordinate of missing square */
int board_size); /* size of board */
void show_Tromino(int size, int x_miss, int y_miss);
int main()
{
int board_size,
x_missing, /* x coordinate of missing square */
y_missing; /* y coordinate of missing square */
do {
printf( "\n-------------------------------------" );
printf( "\nEnter size of board (0 to quit): " );
scanf( "%d", &board_size );
if ( board_size ) {
printf( "\nEnter coordinates of missing square: " );
scanf( "%d%d", &x_missing, &y_missing );
printf( "\n\nTiling\n" );
// if(board[x_board][0] == x_missing && board[0][y_board] == y_missing)
// printf("MS\t");
//board[x_missing][y_missing] = -1;
tromino( 0, 0, x_missing, y_missing, board_size);
show_Tromino(board_size, x_missing, y_missing);
}
} while ( board_size );
return EXIT_SUCCESS;
}
void tromino( int x_board, /* x coordinate of board */
int y_board, /* y coordinate of board */
int x_missing, /* x coordinate of missing square */
int y_missing, /* y coordinate of missing square */
int board_size) /* size of board */
{
int half_size = board_size/2, /* size of subboard */
x_center, /* x coordinate of center of board */
y_center, /* y coordinate of center of board */
x_upper_left, /* x coordinate of missing square in upper
left subboard */
y_upper_left, /* y coordinate of missing square in upper
left subboard */
x_upper_right, /* x coordinate of missing square in upper
right subboard */
y_upper_right, /* y coordinate of missing square in upper
right subboard */
x_lower_right, /* x coordinate of missing square in lower
right subboard */
y_lower_right, /* y coordinate of missing square in lower
right subboard */
x_lower_left, /* x coordinate of missing square in lower
left subboard */
y_lower_left; /* y coordinate of missing square in lower
left subboard */
if ( board_size == 2 ) /* 2x2 board */
{
//Theres too much of nesting for only 4 cases. Got rid of it
if(x_board==x_missing && y_board==y_missing)
board[x_board+1][y_board] = board[x_board][y_board+1]=board[x_board+1][y_board+1]=2;
if(x_board+1==x_missing && y_board==y_missing)
board[x_board][y_board]= board[x_board][y_board+1]=board[x_board+1][y_board+1]=3;
if(x_board==x_missing && y_board+1==y_missing)
board[x_board][y_board]= board[x_board+1][y_board] = board[x_board+1][y_board+1]=1;
if(x_board+1==x_missing && y_board+1==y_missing)
board[x_board][y_board]= board[x_board+1][y_board] = board[x_board][y_board+1]=0;
return;
}
// if(board_size>2)
// { /* compute x and y coordinates of center of board */
x_center = x_board + half_size;
y_center = y_board + half_size;
if((x_missing < x_center) && (y_missing < y_center))
{
//printf("UR\t");
x_upper_left = x_center - 1;
y_upper_left = y_center;
x_upper_right = x_center;
y_upper_right = y_center;
x_lower_left = x_missing;
y_lower_left = y_missing;
x_lower_right = x_center;
y_lower_right = y_center - 1;
board[x_upper_left][y_upper_left]=2; //CHANGE MADE. You forgot to tile the board
board[x_upper_right][y_upper_right]=2;
board[x_lower_right][y_lower_right]=2;
}
if((x_missing >= x_center) && (y_missing < y_center))
{
//printf("UL\t");
x_upper_left = x_center - 1;
y_upper_left = y_center;
x_upper_right = x_center;
y_upper_right = y_center;
x_lower_left = x_center - 1;
y_lower_left = y_center - 1;
x_lower_right = x_missing;
y_lower_right = y_missing;
board[x_upper_left][y_upper_left]=3; //CHANGE MADE. You forgot to tile the board
board[x_upper_right][y_upper_right]=3;
board[x_lower_left][y_lower_left]=3;
}
if((x_missing >= x_center) && (y_missing >= y_center))
{
//printf("LL\t");
x_upper_left = x_center - 1;
y_upper_left = y_center;
x_upper_right = x_missing;
y_upper_right = y_missing;
x_lower_left = x_center - 1;
y_lower_left = y_center - 1;
x_lower_right = x_center;
y_lower_right = y_center - 1;
board[x_upper_left][y_upper_left]=1; //CHANGE MADE. You forgot to tile the board
board[x_lower_left][y_lower_left]=1;
board[x_lower_right][y_lower_right]=1;
}
if((x_missing < x_center) && (y_missing >= y_center))
{
//printf("LR\t");
x_upper_left = x_missing;
y_upper_left = y_missing;
x_upper_right = x_center;
y_upper_right = y_center;
x_lower_left = x_center - 1;
y_lower_left = y_center - 1;
x_lower_right = x_center;
y_lower_right = y_center - 1;
board[x_lower_left][y_lower_left]=0; //CHANGE MADE. You forgot to tile the board
board[x_upper_right][y_upper_right]=0;
board[x_lower_right][y_lower_right]=0;
}
/* tile the four subboards */
tromino( x_board, y_board + half_size,
x_upper_left, y_upper_left, half_size);
tromino( x_board + half_size, y_board + half_size,
x_upper_right, y_upper_right, half_size);
tromino( x_board + half_size, y_board,
x_lower_right, y_lower_right, half_size);
tromino( x_board, y_board,
x_lower_left, y_lower_left, half_size);
}
void show_Tromino(int size, int x_miss, int y_miss)
{
for(int i=size-1;i>=0;i--)
{
for(int j=0; j<size;j++)
{
if(j==x_miss && i==y_miss)
printf("-1");
else
printf("%d ",board[j][i]);
}
printf("\n");
}
//int bsize[Max][Max]; //CHANGE: WTH is bsize? All changes were made to board. Edited and changed them all
}
有一个dynamic recursion
解决方案,还有一个类似的dynamic iteration
解决方案,有助于避免输入非常大时由于深度递归调用而导致的堆栈溢出错误。
分析:
* for a 2*2 cell, could simply fill it, * for a 4*4 cell, * divide it into 4 2*2 smaller squares, * first fill the 2*2 square that already has 1 cell filled, * now the 2*2 square at the center of the original square has 3 empty cells, just fill it with a tile, * now all the 3 remain 2*2 squares divided in previous step, has 1 cell filled, * then for each of the 3 remain 2*2 squares, fill with a tile, * * for a 8*8 cell, * divide it into 4 4*4 smaller squares, * then fill the 4*4 square that already has 1 cell filled, in similar way as a 4*4 input, * now the 2*2 square at the center of the original square has 3 empty cells, just fill it with a tile, * now all the 3 remain 4*4 squares divided in previous step, has 1 cell filled, * then for each of the 3 remain 4*4 squares, fill it in similar way as a 4*4 input, * * for a n*n cell, repeat divide & conquer, steps: * if n = 2, this is base, simple fill a tile, * else * divide it into 4 (n/2 * n/2) squares, * work on the one already with has a tile, by a recursive call, * then put a tile at center of input cell, to fill the (2*2) square in center, * then for each of the 3 (n/2 * n/2) squares, * work on it, by a recursive call, * * * *
类似于上面的Dynamic - recursion
,但它使用循环来避免深度递归调用。
因此它是首选。
分析:
* if it's base case (2*2 square), it's the same as `Dynamic - recursion`, * if it's not base case, * divide it into 4 (n/2 * n/2) squares, mark the one already has a cell filled as A, * then fill (2*2) square at the center of input square first, leave the cell belong to A empty, now all the 4 (n/2 * n/2) squares, has a single cell filled, * * then loop the 4 (n/2 * n/2) squares, for each: * work on it, by a recursive call, * * *
需要它的x
和y
位置。
因此,结构可能如下所示,在c
:
typedef struct {
int x;
int y;
} Cell;
可能有 4 个方向,标记为: 1, 2, 3, 4
;
并且需要L瓦片中间单元格的坐标来定位,
因此,结构可能如下所示,在c
:
typedef struct {
char direction; // 1, 2, 3, 4;
Cell mid; // position of middle cell of tile,
} Tile;
需要左/上单元格来决定它的位置。
和边长决定它的大小。
因此,结构可能如下所示,在c
:
typedef struct {
Cell start; // top/left cell,
int size; // length of side,
} Square;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.