地址:http://acm.hunnu.edu.cn/online/?action=problem&id=10432&type=show
題目在線:
| 棋盤覆蓋問題 |
| Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KB |
| Total submit users: 62, Accepted users: 26 |
| Problem 10432 : No special judgement |
| Problem description |
在一個2k x 2k ( 即:2^k x 2^k )個方格組成的棋盤中,恰有一個方格與其他方格不同,稱該方格為一特殊方格,且稱該棋盤為一特殊棋盤。在棋盤覆蓋問題中,要用圖示的4種不同形態的L型骨牌覆蓋給定的特殊棋盤上除特殊方格以外的所有方格,且任何2個L型骨牌不得重疊覆蓋。![]() |
| Input |
| 輸入文件第一行是一個整數T,表示有多少組測試數據,接下來是T組測試數據,共2T行,每組第一行為整數n,是2的n次冪(1<=n<=64),表示棋盤的大小為n*n,第二行是兩個整數,代表特殊方格所在行號和列號。 |
| Output |
| 先輸出“CASE:i,然后按樣例輸出。數據間用制表符隔開(‘t’),每行最后一個數據后無制表符。 |
| Sample Input |
2 2 0 0 8 2 2 |
| Sample Output |
CASE:1 0 1 1 1 CASE:2 3 3 4 4 8 8 9 9 3 2 2 4 8 7 7 9 5 2 0 6 10 10 7 11 5 5 6 6 1 10 11 11 13 13 14 1 1 18 19 19 13 12 14 14 18 18 17 19 15 12 12 16 20 17 17 21 15 15 16 16 20 20 21 21 |
| Judge Tips |
| 要求遍歷順序按從左到右,從上到下。 |
| Problem Source |
| qshj |
思路:
雖然這個問題已經在網上被討論遍了,但是最近從新拾起算法,感覺有必要夯實一下基礎。
棋盤覆蓋問題:
首先大致描述一下題目:
在一個2^k×2^k個方格組成的棋盤中,若有一個方格與其他方格不同,則稱該方格為一特殊方格,且稱該棋盤為一個特殊棋盤.顯然特殊方格在棋盤上出現的位置有4^k種情形.因而對任何
k≥0,有4^k種不同的特殊棋盤.
下圖–圖(1)中的特殊棋盤是當k=2時16個特殊棋盤中的一個:
圖(1)
題目要求在棋盤覆蓋問題中,要用下圖—圖(2)所示的4種不同形態的L型骨牌覆蓋一個給定的特殊棋盤上除特殊方格以外的所有方格,且任何2個L型骨牌不得重疊覆蓋.
圖(2)
思路分析:
當k>0時,將2^k×2^k棋盤分割為4個2^k-1×2^k-1子棋盤,如下圖–圖(3)所示:
圖(3)
特殊方格必位於4個較小子棋盤之一中,其余3個子棋盤中無特殊方格.為了將這3個無特殊方格的子棋盤轉化為特殊棋盤,可以用一個L型骨牌覆蓋這3個較小棋盤的會合處。
如下圖–圖(4)所示,這3個子棋盤上被L型骨牌覆蓋的方格就成為該棋盤上的特殊方格,從而原問題轉化為4個較小規模的棋盤覆蓋問題.遞歸地使用這種分割,直至棋盤簡化為1×1棋盤。
別人的代:1:
1 #include<iostream> 2 using namespace std; 3 int tile=1; //L型骨牌的編號(遞增) 4 int board[100][100]; //棋盤 5 /***************************************************** 6 * 遞歸方式實現棋盤覆蓋算法 7 * 輸入參數: 8 * tr--當前棋盤左上角的行號 9 * tc--當前棋盤左上角的列號 10 * dr--當前特殊方格所在的行號 11 * dc--當前特殊方格所在的列號 12 * size:當前棋盤的:2^k 13 *****************************************************/ 14 void chessBoard ( int tr, int tc, int dr, int dc, int size ) 15 { 16 if ( size==1 ) //棋盤方格大小為1,說明遞歸到最里層 17 return; 18 int t=tile++; //每次遞增1 19 int s=size/2; //棋盤中間的行、列號(相等的) 20 //檢查特殊方塊是否在左上角子棋盤中 21 if ( dr<tr+s && dc<tc+s ) //在 22 chessBoard ( tr, tc, dr, dc, s ); 23 else //不在,將該子棋盤右下角的方塊視為特殊方塊 24 { 25 board[tr+s-1][tc+s-1]=t; 26 chessBoard ( tr, tc, tr+s-1, tc+s-1, s ); 27 } 28 //檢查特殊方塊是否在右上角子棋盤中 29 if ( dr<tr+s && dc>=tc+s ) //在 30 chessBoard ( tr, tc+s, dr, dc, s ); 31 else //不在,將該子棋盤左下角的方塊視為特殊方塊 32 { 33 board[tr+s-1][tc+s]=t; 34 chessBoard ( tr, tc+s, tr+s-1, tc+s, s ); 35 } 36 //檢查特殊方塊是否在左下角子棋盤中 37 if ( dr>=tr+s && dc<tc+s ) //在 38 chessBoard ( tr+s, tc, dr, dc, s ); 39 else //不在,將該子棋盤右上角的方塊視為特殊方塊 40 { 41 board[tr+s][tc+s-1]=t; 42 chessBoard ( tr+s, tc, tr+s, tc+s-1, s ); 43 } 44 //檢查特殊方塊是否在右下角子棋盤中 45 if ( dr>=tr+s && dc>=tc+s ) //在 46 chessBoard ( tr+s, tc+s, dr, dc, s ); 47 else //不在,將該子棋盤左上角的方塊視為特殊方塊 48 { 49 board[tr+s][tc+s]=t; 50 chessBoard ( tr+s, tc+s, tr+s, tc+s, s ); 51 } 52 } 53 54 void main() 55 { 56 int size; 57 cout<<"輸入棋盤的size(大小必須是2的n次冪): "; 58 cin>>size; 59 int index_x,index_y; 60 cout<<"輸入特殊方格位置的坐標: "; 61 cin>>index_x>>index_y; 62 chessBoard ( 0,0,index_x,index_y,size ); 63 for ( int i=0; i<size; i++ ) 64 { 65 for ( int j=0; j<size; j++ ) 66 cout<<board[i][j]<<"/t"; 67 cout<<endl; 68 } 69 }
別人代碼2:
1 #include <iostream> 2 using namespace std; 3 const int N = 11; 4 int Board[N][N]; 5 int tile = 0; 6 7 /* 8 tr:棋盤左上角方格的行號 9 tc:棋盤左上角方格的列號 10 dr:特殊方格所在的行號 11 dc:特殊方格所在的列號 12 size:方形棋盤的邊長 13 */ 14 void ChessBoard(int tr, int tc, int dr, int dc, int size) 15 { 16 if(size == 1) 17 return; 18 int t = ++tile, s = size/2; 19 20 //覆蓋左上角子棋盤 21 if(dr<tr+s && dc<tc+s) 22 //特殊方格在此棋盤中 23 ChessBoard(tr, tc, dr, dc, s); 24 else // 此棋盤無特殊方格 25 { 26 // 用t號L型骨型牌覆蓋右下角 27 Board[tr+s-1][tc+s-1] = t; 28 // 覆蓋其余方格 29 ChessBoard(tr, tc, tr+s-1, tc+s-1, s); 30 } 31 32 //覆蓋右上角子棋盤 33 if(dr<tr+s && dc>=tc+s) 34 ChessBoard(tr, tc+s, dr, dc, s); 35 else 36 { 37 Board[tr+s-1][tc+s] = t; 38 ChessBoard(tr, tc+s, tr+s-1, tc+s, s); 39 } 40 41 //覆蓋左下角子棋盤 42 if(dr>=tr+s && dc<tc+s) 43 ChessBoard(tr+s, tc, dr, dc, s); 44 else 45 { 46 Board[tr+s][tc+s-1] = t; 47 ChessBoard(tr+s, tc, tr+s, tc+s-1, s); 48 } 49 50 //覆蓋右下角子棋盤 51 if(dr>=tr+s && dc>=tc+s) 52 ChessBoard(tr+s, tc+s, dr, dc, s); 53 else 54 { 55 Board[tr+s][tc+s] = t; 56 ChessBoard(tr+s, tc+s, tr+s, tc+s, s); 57 } 58 } 59 60 void DisplayBoard(int size) 61 { 62 for(int i=1; i<=size; ++i) 63 { 64 for(int j=1; j<=size; ++j) 65 printf("%2d ", Board[i][j]); 66 printf("\n"); 67 } 68 } 69 70 int main() 71 { 72 ChessBoard(1, 1, 1, 2, 4); 73 DisplayBoard(4); 74 return 0; 75 }

