題目分析
在一個 2k*2k 個方格組成的棋盤中,若恰有一個方格與其他方格不同,則稱該方格爲一個特殊方格,且稱棋盤爲特殊棋盤。
在棋盤覆蓋問題中,要用到4中不同形態的L型骨牌覆蓋一個給定的特殊棋盤上除特殊方格意外的所有方格,且任何2個L型骨牌不得重疊覆蓋。
分治法
視頻講解
超簡單!棋盤覆蓋+代碼實現
代碼
public class qipan {
int tile = 1;//表示L型骨牌的編號
int[][] board = new int[100][100];//表示棋盤
//處理帶有特殊棋子的棋盤.tr、tc表示棋盤的入口即左上角的行列號,dr、dc表示特殊棋子的行列位置,size表示棋盤的大小
public void ChessBoard(int tr, int tc, int dr, int dc, int size) {
if (size == 1) { //如果棋盤大小=1,就說明不能再進行劃分
return; //即到達遞歸邊界 返回 退出方法
}
int t = tile++;
int s = size / 2;//每一次化大棋盤爲一半的子棋盤
//要處理帶有特殊棋子的棋盤,第一步先處理左上棋盤
if (dr < tr + s && dc < tc + s)//左上角子棋盤有特殊棋子
{
ChessBoard(tr, tc, dr, dc, s);
}//處理有特殊棋子的左上角子棋盤
else//處理無特殊棋子的左上角子棋盤
{
//設左上角子棋盤的右下角爲特殊棋子,用t型的骨牌覆蓋。
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;//設右上角子棋盤的左下角爲特殊棋子,用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 {
board[tr + s][tc + s - 1] = t;//設左下角子棋盤的右上角爲特殊棋子,用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;//設子棋盤右下角的左上角爲特殊棋子,用t型的骨牌覆蓋。
ChessBoard(tr + s, tc + s, tr + s, tc + s, s);//處理有用 骨牌覆蓋的格子作爲特殊棋子的右下角子棋盤
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("請輸入棋盤的大小(size)");
int size = sc.nextInt(); //棋盤大小
System.out.println("請輸入特殊棋子的位置(dr,dc)");
int dr = sc.nextInt();
int dc = sc.nextInt();
//調用方法
qipan c = new qipan();
//(0,0)左上角的方格位置 (dr,dc特殊方格位置) size棋盤大小
c.ChessBoard(0, 0, dr, dc, size);
//輸出棋盤
for (int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
System.out.print(String.format("%5d", c.board[i][j]));
}
System.out.println();
}
}
}
代碼截圖