分治算法--棋盤覆蓋

分治算法--棋盤覆蓋

 

問題描述

在一個2^k×2^k 個方格組成的棋盤中,恰有一個方格與其他方格不同,稱該方格爲一特殊方格,且稱該棋盤爲一特殊棋盤。在棋盤覆蓋問題中,要用圖示的4種不同形態的L型骨牌覆蓋給定的特殊棋盤上除特殊方格以外的所有方格,且任何2個L型骨牌不得重疊覆蓋。

解題思路

分析:當k>0時,將2k×2k棋盤分割爲4個2^k-1×2^k-1 子棋盤(a)所示。特殊方格必位於4個較小子棋盤之一中,其餘3個子棋盤中無特殊方格。爲了將這3個無特殊方格的子棋盤轉化爲特殊棋盤,可以用一個L型骨牌覆蓋這3個較小棋盤的會合處,如 (b)所示,從而將原問題轉化爲4個較小規模的棋盤覆蓋問題。遞歸地使用這種分割,直至棋盤簡化爲棋盤1×1。(出自算法設計與分析-王曉東)

實現:每次都對分割後的四個小方塊進行判斷,判斷特殊方格是否在裏面。這裏的判斷的方法是每次先記錄下整個大方塊的左上角(top left coner)方格的行列座標,然後再與特殊方格座標進行比較,就可以知道特殊方格是否在該塊中。如果特殊方塊在裏面,這直接遞歸下去求即可,如果不在,這根據分割的四個方塊的不同位置,把右下角、左下角、右上角或者左上角的方格標記爲特殊方塊,然後繼續遞歸。在遞歸函數裏,還要有一個變量s來記錄邊的方格數,每次對方塊進行劃分時,邊的方格數都會減半,這個變量是爲了方便判斷特殊方格的位置。其次還要有一個變nCount來記錄L型骨牌的數量。

代碼實現:

複製代碼
#include <stdio.h>
#include <stdlib.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("%d",&size);
    scanf("%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)
{
    //tr and tc represent the top left corner's coordinate of the matrix
    int s,t;
    if (1 == size) return;

    s = size/2; //The number of grid the matrix's edge
    t = ++ nCount;

    //locate the special  grid on bottom right corner
    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);
    }

    //locate the special  grid on bottom left corner
    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);
    }

    //locate the special  grid on top right corner
    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);
    }

    //locate the special  grid on top left corner
    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);
    }

}
2013/6/14  22:30
複製代碼

 

程序結果:

發佈了26 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章