遞歸與分治策略之棋盤覆蓋問題

棋盤覆蓋

       在一個2^k * 2^k 個方格組成的棋盤中,若恰好有一個方格與其他方格不同,則稱該房改爲一特殊方格,且稱該棋盤爲一特殊棋盤。顯然特殊方格在棋盤上出現的位置有4^k種情況。

       在棋盤覆蓋問題中,要用如下圖所示的4種不同形態的L型骨牌覆蓋一個給定的特殊棋盤上除特殊方格以外的所有方格,且任何2個L型骨牌不得重複覆蓋。可知,在任何一個2^k * 2^k的棋盤覆蓋中,用到的L型骨牌的個數恰爲(4^k - 1)/3。

                            

                                                                      

特殊棋盤圖

                                                                      

算法思想:用分治策略,可以設計解棋盤覆蓋爲題的一個算法。當k > 0時,將2^k * 2^k棋盤分割爲4個2^k-1 * 2^k-1字棋盤,特殊方格必位於4個子棋盤之一中,其餘3個子棋盤中無特殊方格。爲了這3個無特殊方格的子棋盤轉化爲特殊棋盤,我們用一個L型骨牌覆蓋這3個子棋盤的匯合處,如下圖:

 

                                                                     

從而將原問題轉化爲4個子棋盤覆蓋問題。遞歸的使用這種分割,直至棋盤簡化爲1*1棋盤。

 

       實現這種分治策略的算法可描述如下:

#include <iostream>
#include <cstring>

using namespace std;

const int MAX_SIZE = 10;

int tite = 1;
int board[MAX_SIZE][MAX_SIZE];

/*
函數名稱:ChessBoard
函數功能:實現2^k * 2^k 的棋盤覆蓋
函數參數:
        tr:棋盤左上角的行號
        tc:棋盤左上角的列號
        dr:特殊方格的行號
        dc:特殊方格的列號
        size:棋盤規格大小
        tite:L型骨牌的編號 其初始值爲1 全局變量
返回值:無
*/

void ChessBoard(int tr, int tc, int dr, int dc, int size)
{
    if(size == 1)
        return ;
    int t = tite++;
    int s = size/2;
    //覆蓋左上角子棋盤
    if((dr < tr + s) && (dc < tc + s))
    {
        //特殊方格在此棋盤中
        ChessBoard(tr, tc, dr, dc, s);
    }
    else
    {
        board[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
    {
        board[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 + s - 1), dr, dc, s);
    }
    else
    {
        board[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
    {
        board[tr + s][tc + s] = t;
        ChessBoard((tr + s), (tc + s), (tr + s), (tc + s), s);
    }
}

int main()
{
    int n = 0;
    while(cin >> n)
    {
        memset(board, -1, sizeof(board));
        board[2][2] = 0;
        ChessBoard(0, 0, 2, 2, n);

        for(int i = 0;i < n;++i)
        {
            for(int j = 0; j < n; ++j)
                cout << board[i][j];
            cout << endl;
        }
    }
    return 0;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章