具體的題目是:
有一個 的方格棋盤,恰有一個方格是黑色的,其它爲白色。你的任務是用包含3個方格的L型牌覆蓋所有白色方格。黑方格不能被覆蓋,且任意一個白色方格不能同時被兩個或者多個L型牌覆蓋。如圖爲L型牌的4種旋轉方式。
問題分析:
我們很容易想到用遞歸的方法去解決這個問題,在經典的遞歸問題漢諾塔問題中我們,把N個盤子的問題分解成N-1個問題去遞歸解決。那麼我們也可以往這方面想,這個棋盤規格是2^k*2^K,那麼我們可以將k減去1,將大棋盤分成小棋盤來解決。於是大棋盤被分成了四個小棋盤,可是新的問題來了,雖然把棋盤分解了可是隻有一個棋盤裏是有黑塊的,這樣沒法進行遞歸。既然沒有那麼我們就想辦法給它添上,而且每分一次就添一次,保證遞歸的進行。問題的關鍵是怎麼添,添在哪裏?根據這個L形的形狀,可以在分割的中心的添上一個L形。如圖所示:
然後遞歸就可以順利的進行了。總結一下過程:
- 遞歸的結束條件當:k=0時,也就是不在是一個棋盤的時候,可能會有人問問什麼不是k=1時,因爲k=1時依然需要繼續把另外三個地方添上黑塊。
- 遞歸關係,將大棋盤分解爲小棋盤遞歸解決。
好了不說了上代碼:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int nCount = 0;
int Matrix[100][100];
void chessBoard(int tr, int tc, int dr, int dc, int size);
int main()
{
int size, r, c, row, col;
memset(Matrix, 0, sizeof(Matrix));
scanf_s("%d", &size);
scanf_s("%d%d", &row, &col);
chessBoard(0, 0, row, col, size);
for (r = 0; r < size; r++)
{
for (c = 0; c < size; c++)
{
printf("%2d ", Matrix[r][c]);
}
printf("\n");
}
return 0;
}
void chessBoard(int tr, int tc, int dr, int dc, int size)
{
int s, t;
if (1 == size) return;
s = size / 2;
t = ++nCount;
if (dr < tr + s && dc < tc + s)
{
chessBoard(tr, tc, dr, dc, s);
}
else
{
Matrix[tr + s - 1][tc + s - 1] = t;
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
{
Matrix[tr + s - 1][tc + s] = t;
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
{
Matrix[tr + s][tc + s - 1] = t;
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
{
Matrix[tr + s][tc + s] = t;
chessBoard(tr + s, tc + s, tr + s, tc + s, s);
}
}
這是我的一點點理解,有什麼不對的請大家批評指正,歡迎評論。