用分治法解决棋盘覆盖算法
分治法基本思想
分治法字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础。三步骤:分,治,和
分–将问题分解为规模更小的子问题;
治–将这些规模更小的子问题逐个击破;
合–将已解决的子问题合并,最终得出"母"问题的解;
算法
void chessBoard(int tr, int tc, int x, int y, int size)
{
if(size == 1)return;///当划分棋盘为1X1时结束递归
int t = tile++;
int s = size / 2;///每次递归二分棋盘规模
///若特殊方格在左上棋盘,则对该子棋盘递归覆盖;否则用相应号码骨牌覆盖其右下方格并将此方格看作特殊方格继续递归
if(x < tr+s && y < tc+s)
chessBoard(tr, tc, x, y, s);
else{
board[tr+s-1][tc+s-1] = t;
chessBoard(tr, tc, tr+s-1, tc+s-1, s);///递归,第三四个参数为刚覆盖的骨牌坐标
}
///若特殊方格在右上棋盘,则对该子棋盘递归覆盖;否则用相应号码骨牌覆盖其左下方格并将此方格看作特殊方格继续递归
if(x < tr+s && y >= tc+s)
chessBoard(tr, tc+s, x, y, s);
else{
board[tr+s-1][tc+s] = t;
chessBoard(tr, tc+s, tr+s-1, tc+s, s);
}
///若特殊方格在左下棋盘,则对该子棋盘递归覆盖;否则用相应号码骨牌覆盖其右上方格并将此方格看作特殊方格继续递归
if(x >= tr+s && y < tc+s)
chessBoard(tr+s, tc, x, y, s);
else{
board[tr+s][tc+s-1] = t;
chessBoard(tr+s, tc, tr+s, tc+s-1, s);
}
///若特殊方格在右下棋盘,则对该子棋盘递归覆盖;否则用相应号码骨牌覆盖其左上方格并将此方格看作特殊方格继续递归
if(x >= tr+s && y >= tc+s)
chessBoard(tr+s, tc+s, x, y, s);
else{
board[tr+s][tc+s] = t;
chessBoard(tr+s, tc+s, tr+s, tc+s, s);
}
}
完整源代码
#include <iostream>
#include <math.h>
using namespace std;
int k,x,y;
long int size;///棋盘大小
int tile = 1;///L型骨牌的编号
int board[1024][1024];///二维数组初始化
void chessBoard(int tr, int tc, int x, int y, int size)
{
if(size == 1)return;///当划分棋盘为1X1时结束递归
int t = tile++;
int s = size / 2;///每次递归二分棋盘规模
///若特殊方格在左上棋盘,则对该子棋盘递归覆盖;否则用相应号码骨牌覆盖其右下方格并将此方格看作特殊方格继续递归
if(x < tr+s && y < tc+s)
chessBoard(tr, tc, x, y, s);
else{
board[tr+s-1][tc+s-1] = t;
chessBoard(tr, tc, tr+s-1, tc+s-1, s);///递归,第三四个参数为刚覆盖的骨牌坐标
}
///若特殊方格在右上棋盘,则对该子棋盘递归覆盖;否则用相应号码骨牌覆盖其左下方格并将此方格看作特殊方格继续递归
if(x < tr+s && y >= tc+s)
chessBoard(tr, tc+s, x, y, s);
else{
board[tr+s-1][tc+s] = t;
chessBoard(tr, tc+s, tr+s-1, tc+s, s);
}
///若特殊方格在左下棋盘,则对该子棋盘递归覆盖;否则用相应号码骨牌覆盖其右上方格并将此方格看作特殊方格继续递归
if(x >= tr+s && y < tc+s)
chessBoard(tr+s, tc, x, y, s);
else{
board[tr+s][tc+s-1] = t;
chessBoard(tr+s, tc, tr+s, tc+s-1, s);
}
///若特殊方格在右下棋盘,则对该子棋盘递归覆盖;否则用相应号码骨牌覆盖其左上方格并将此方格看作特殊方格继续递归
if(x >= tr+s && y >= tc+s)
chessBoard(tr+s, tc+s, x, y, s);
else{
board[tr+s][tc+s] = t;
chessBoard(tr+s, tc+s, tr+s, tc+s, s);
}
for(int i=0; i<pow(2,k); ++i){///每次递归结束都输出一次
for(int j=0; j<pow(2,k); ++j){
cout.width(4);
cout<<board[i][j];
}
cout<<endl;
}
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
}
int main()
{
cout<<"棋盘规格为2^k,请键入k的值:"<<endl;
cin>>k;
cout<<"请键入特殊方格的位置:"<<endl;
cin>>x>>y;
board[x][y]=-1;///特殊方格标注-1
size=pow(2,k);///方格格式
chessBoard(0, 0, x, y, size);
return 0;
}