【问题标题】:How do I solve this tromino tiling problem?如何解决这个 tromino 平铺问题?
【发布时间】:2020-06-29 08:15:18
【问题描述】:

我正在尝试为 n x n 板解决这个 tromino 拼贴问题。鉴于 n x n 棋盘中缺少正方形坐标 (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

注意:

  • UL- 左上
  • UR- 右上角
  • LL- 左下
  • LR- 右下
  • MS- 缺失的正方形

【问题讨论】:

  • 请注意,您正在重新定义x_boardy_board。另外,我会在嵌套的if 中使用一些大括号,以确保实际逻辑符合预期。
  • @Bob__ 我试过了,但没用
  • 在调试器中单步调试代码的绝佳机会。在放置一块的位置之前和之后放置一个断点,看看它是否有意义。

标签: c algorithm recursion divide-and-conquer


【解决方案1】:

问题是由于基本情况造成的。在求解 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

}

【讨论】:

  • 啊..为了一些声誉你必须经历的痛苦。完毕。用代码更新了答案
  • 我想提一下,我还没有费心完全修复​​您的代码。它仍然会因电路板尺寸而不是 2 的幂而崩溃。我刚刚让它工作得足以显示正确的输出以提供正确的输入
【解决方案2】:

有一个dynamic recursion的解决方案,和一个类似的dynamic iteration的解决方案,这有助于避免在输入非常大时由于深度递归调用而导致堆栈溢出错误。


动态 - 递归

分析:

* 对于 2*2 单元格,可以简单地填充它, * 对于 4*4 单元格, * 把它分成 4 个 2*2 的小方块, * 首先填充已经填充了 1 个单元格的 2*2 正方形, * 现在原正方形中心的 2*2 正方形有 3 个空单元格,只需用瓷砖填充即可, * 现在所有 3 个仍然在上一步中划分为 2*2 的正方形,填充了 1 个单元格, * 然后对于剩下的 3 个 2*2 方块中的每一个,用瓷砖填充, * * 对于 8*8 单元格, * 把它分成 4 个 4*4 的小方块, * 然后填充已经填充了 1 个单元格的 4*4 正方形,与 4*4 输入类似, * 现在原正方形中心的 2*2 正方形有 3 个空单元格,只需用瓷砖填充即可, * 现在所有 3 个仍然在上一步中划分为 4*4 的正方形,填充了 1 个单元格, * 然后对于剩下的 3 个 4*4 正方形中的每一个,以与 4*4 输入类似的方式填充它, * * 对于 n*n 单元格, 重复分而治之, 脚步: * 如果 n = 2, 这是基础,简单地填充瓷砖, * 别的 * 将其分成 4 (n/2 * n/2) 个正方形, * 通过递归调用,在已经有瓷砖的瓷砖上工作, * 然后在输入单元格的中心放置一个图块,以填充中心的 (2*2) 正方形, * 然后对于 3 (n/2 * n/2) 个正方形中的每一个, * 通过递归调用处理它, * * * *

动态 - 迭代

类似于上面的Dynamic - recursion,但它使用循环来避免深度递归调用。

因此它是首选

分析:

* 如果是基本情况(2*2 正方形), 它与“动态 - 递归”相同, * 如果不是基本情况, * 将其分成 4 (n/2 * n/2) 个方格,将已填满单元格的方格标记为 A, * 然后先在输入正方形的中心填充 (2*2) 正方形,将属于 A 的单元格留空, 现在所有 4 (n/2 * n/2) 个正方形,都填充了一个单元格, * * 然后循环 4 (n/2 * n/2) 个正方形,每个: * 通过递归调用处理它, * * *

形状的表示

  • 细胞

需要它的xy 位置。

因此结构可能看起来像这样,在c:

typedef struct {
    int x;
    int y;
} Cell;
  • L 瓦

可能有4个方向,标记为:1, 2, 3, 4;
并且需要L个tile的中间cell的坐标来定位,

因此结构可能如下所示,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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-07
    • 1970-01-01
    • 2019-04-20
    • 2011-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多