問題描述
在一個2k×2k (k≥0)個方格組成的棋盤中,恰有一個方格與其他方格不同,稱該方格爲特殊方格。顯然,特殊方格在棋盤中可能出現的位置有4k種,因而有4k種不同的棋盤,圖4.10(a)所示是k=2時16種棋盤中的一個。棋盤覆蓋問題(chess cover problem)要求用圖4.10(b)所示的4種不同形狀的L型骨牌覆蓋給定棋盤上除特殊方格以外的所有方格,且任何2個L型骨牌不得重疊覆蓋。
實現:
- 每次都對分割後的四個小方塊進行判斷,判斷特殊方格是否在裏面。
- 這裏的判斷的方法是每次先記錄下整個大方塊的左上角topLeftConer
方格的行列座標 - 然後再與特殊方格座標進行比較,就可以知道特殊方格是否在該塊中。
- 如果特殊方塊在裏面,直接遞歸下去求即可
- 如果不在,這根據分割的四個方塊的不同位置,把右下角、左下角、右上角或者左上角的方格標記爲特殊方塊,然後繼續遞歸。
注意: 在遞歸函數裏,還要有一個變量s來記錄邊的方格數,每次對方塊進行劃分時,邊的方格數都會減半,這個變量是爲了方便判斷特殊方格的位置。其次還要有一個變nCount來記錄L型骨牌的數量。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int nCount = 0,t=0;
int board[100][100];
// void chessBoard(int tr, int tc, int dr, int dc, int size);
void ChessBoard(int tr, int tc, int dr, int dc, int size)
{
int s, t1; //t1表示本次覆蓋所用L型骨牌的編號
if (size == 1)
return; //棋盤只有一個方格且是特殊方格
t1 = ++t; // L型骨牌編號
s = size / 2; // 劃分棋盤
if (dr < tr + s && dc < tc + s) //特殊方格在左上角子棋盤中
ChessBoard(tr, tc, dr, dc, s); //遞歸處理子棋盤
else
{ //用 t1號L型骨牌覆蓋右下角,再遞歸處理子棋盤
board[tr + s - 1][tc + s - 1] = t1;
ChessBoard(tr, tc, tr + s - 1, tc + s - 1, s);
}
if (dr < tr + s && dc >= tc + s) //特殊方格在右上角子棋盤中
ChessBoard(tr, tc + s, dr, dc, s); //遞歸處理子棋盤
else
{ //用 t1號L型骨牌覆蓋左下角,再遞歸處理子棋盤
board[tr + s - 1][tc + s] = t1;
ChessBoard(tr, tc + s, tr + s - 1, tc + s, s);
}
if (dr >= tr + s && dc < tc + s) //特殊方格在左下角子棋盤中
ChessBoard(tr + s, tc, dr, dc, s); //遞歸處理子棋盤
else
{ //用 t1號L型骨牌覆蓋右上角,再遞歸處理子棋盤
board[tr + s][tc + s - 1] = t1;
ChessBoard(tr + s, tc, tr + s, tc + s - 1, s);
}
if (dr >= tr + s && dc >= tc + s) //特殊方格在右下角子棋盤中
ChessBoard(tr + s, tc + s, dr, dc, s); //遞歸處理子棋盤
else
{ //用 t1號L型骨牌覆蓋左上角,再遞歸處理子棋盤
board[tr + s][tc + s] = t1;
ChessBoard(tr + s, tc + s, tr + s, tc + s, s);
}
}
int main()
{
int size, r, c, row, col;
memset(board, 0, sizeof(board));
scanf("%d", &size); //方陣大小
scanf("%d%d", &row, &col); //特殊點,座標從1開始
ChessBoard(0, 0, row, col, size);
for (r = 0; r < size; r++)
{
for (c = 0; c < size; c++)
{
printf("%2d ", board[r][c]);
}
printf("\n");
}
return 0;
}
參考鏈接:
代碼思路,編輯格式不易,大家覺得還可以可以點贊、收藏、關注一下吧!
也可以到我的個人博客參觀一下,https://motongxue.gitee.io