1. 程式人生 > >演算法07:棋盤覆蓋——分治法Part3

演算法07:棋盤覆蓋——分治法Part3

(3)棋盤覆蓋

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


分治法的思想:當k>0時,將2k×2k棋盤分割為4個2k-1×2k-1 子棋盤。特殊方格必位於4個較小子棋盤之一中,其餘3個子棋盤中無特殊方格。為了將這3個無特殊方格的子棋盤轉化為特殊棋盤,可以用一個L型骨牌覆蓋這3個較小棋盤的會合處,從而將原問題轉化為4個較小規模的棋盤覆蓋問題。遞迴地使用這種分割,直至棋盤簡化為棋盤1×1。 


具體演算法:

(1)將棋盤分為4部分,檢查特殊方格是否在左上部分

          a.在,繼續將左上部分分割;

          b.不在,將這部分右下角的格子填充,作為特殊方格,繼續分割;

(2)將左下角、右上角、右下角按同樣的方式處理

(3)遞迴棋盤為1*1時結束

完整演算法

#include <cstdlib>
#include <iostream>

using namespace std;

int board[100][100];
int t0 = 0;

void chess_board(int dx, int dy, int tx, int ty, int size )
{
      if(size == 1) return;
      
      int t = ++t0;
      
      int s = size/2;
      
      //檢查特殊格是否在左上部分
      if(tx < dx+s && ty < dy+s) {
           chess_board(dx, dy, tx, ty, s); 
      }
      else{//不在右下角填充 
            board[dx+s-1][dy+s-1] = t;
            chess_board(dx, dy, dx+s-1, dy+s-1, s);
      }
      //檢查特殊格是否在左下部分
      if(tx >= dx+s && ty < dy+s) {
           chess_board(dx+s, dy, tx, ty, s); 
      }
      else{//不在右上角填充 
            board[dx+s][dy+s-1] = t;
            chess_board(dx+s, dy, dx+s, dy+s-1, s);
      }
      //檢查特殊格是否在右上部分
      if(tx < dx+s && ty >= dy+s) {
           chess_board(dx, dy+s, tx, ty, s); 
      }
      else{//不在左下角填充 
            board[dx+s-1][dy+s] = t;
            chess_board(dx, dy+s, dx+s-1, dy+s, s);
      }
      //檢查特殊格是否在右下部分 
      if(tx >= dx+s && ty >= dy+s) {
           chess_board(dx+s, dy+s, tx, ty, s) ;
      }
      else{//不在左上角填充 
            board[dx+s][dy+s] = t;
            chess_board(dx+s, dy+s, dx+s, dy+s, s);
      }            
}

int main()
{
    int size, x, y;
    
    while(cin>>size>>x>>y){
    
         chess_board(0, 0, x, y, size);
    
         for(int i = 0; i < size; i++){
               for(int j = 0; j < size; j++){
                    cout<<board[i][j]<<" ";
               }
               cout<<endl;
         }
    }
    
    system("PAUSE");
    return 0;
}

執行結果: