最近有點無聊敲了一下棋盤覆蓋問題。
一:算法分析
棋盤覆蓋問題要求在2^k * 2^k 個方格組成的棋盤中,你給定任意一個特殊點,用一種方案實現對除該特殊點的棋盤實現全覆蓋。
建立模型如圖:
解決方案就是利用分治法,將方形棋盤分成4部分,如果該特殊點在某一部分,我們就去遞歸他,如果不在某一部分,我們假設一個點為特殊點,同樣遞歸下去,知道全覆蓋。
左上角的子棋盤(若不存在特殊方格):則將該子棋盤右下角的那個方格假設為特殊方格;
右上角的子棋盤(若不存在特殊方格):則將該子棋盤左下角的那個方格假設為特殊方格;
左下角的子棋盤(若不存在特殊方格):則將該子棋盤右上角的那個方格假設為特殊方格;
右下角的子棋盤(若不存在特殊方格):則將該子棋盤左上角的那個方格假設為特殊方格;
代碼實現:
#include<iostream>
using namespace std;
int map[10][10];
int n = 1;//從1開始填
void solve(int a, int b,int xl,int xr,int yl,int yr) {//要傳入的參數有特殊點的坐標x和y,x軸的邊界xl到xr,y軸的邊界為yl到yr
if (xl == xr || yl == yr) {
return;//已經全部填完,跳出遞歸
}
int xm = (xl + xr) / 2;//這個是x軸邊界的中位數
int ym = (yl + yr) / 2;//y軸邊界的中位數(這兩個參數用來判斷特殊點在棋盤的位置)
if (a > xm && b <= ym) { //右上角是黑塊
map[ym][xm] = n;//右上角是黑塊,那么左上角中間的位置要填n,然后將這一塊視為黑塊(特殊點),這個黑塊屬於左上角分治出的區域。
map[ym + 1][xm] = n;//理由同上,這個將成為左下角的黑塊,並屬於左下角的分治出的區域。
map[ym + 1][xm + 1] = n;//這個是右下角,道理同上。
n++;
solve(a, b, xm + 1, xr, yl, ym);//注意第一個和第二個參數那里是a和b,將分治出的右上角的區域進行遞歸。
solve(xm + 1, ym + 1, xm + 1, xr, ym+1, yr);//這里是將右下角分治出的區域進行遞歸,注意第一個和第二個參數。
solve(xm, ym, xl, xm, yl, ym);//這里是左上角,道理和上面一樣。
solve(xm, ym + 1, xl, xm, ym + 1, yr);//這里是左下角,道理和上面一樣。
}
if(a <= xm && b >ym) { //左下角是黑塊
map[ym][xm] = n;
map[ym][xm+1] = n;
map[ym + 1][xm + 1] = n;
n++;
solve(a, b, xl, xm, ym+1, yr);
solve(xm, ym, xl, xm, yl, ym);
solve(xm+1, ym, xm + 1, xr, yl, ym);
solve(xm + 1, ym + 1, xm + 1, xr, ym+1, yr);
}
if (a > xm && b > ym) {//右下角是黑塊
map[ym][xm] = n;
map[ym][xm + 1] = n;
map[ym + 1][xm] = n;
n++;
solve(a, b, xm + 1, xr, ym+1, yr);
solve(xm, ym, xl, xm, yl, ym);
solve(xm + 1, ym, xm + 1, xr, yl, ym);
solve(xm, ym + 1, xl, xm, ym + 1, yr);
}
if (a <= xm && b <= ym) { //左上角是黑塊
map[ym+1][xm+1] = n;
map[ym][xm + 1] = n;
map[ym + 1][xm] = n;
n++;
solve(a, b, xl, xm, yl, ym);
solve(xm + 1, ym + 1, xm + 1, xr, ym+1, yr);
solve(xm + 1, ym, xm + 1, xr, yl, ym);
solve(xm, ym + 1, xl, xm, ym + 1, yr);
}
}
int main() {
int a, b;
cin >> a >> b;
solve(a, b, 0, 7, 0, 7);//這里的意思是8*8的棋盤,然后特殊點的位置為(a,b)
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) cout << map[i][j]<<"\t";
cout << endl;
}
return 0;
}