棋盘覆盖问题——分治法

最近有点无聊敲了一下棋盘覆盖问题。

一:算法分析

棋盘覆盖问题要求在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;
}

posted on 2019-10-29 21:55  梁锋华  阅读(945)  评论(0编辑  收藏  举报