分治与递归-棋盘覆盖问题
Posted qq77530202
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分治与递归-棋盘覆盖问题相关的知识,希望对你有一定的参考价值。
在一个2^k×2^k个方格组成的棋盘中,若有一个方格与其他方格不同,则称该方格为一特殊方格,且称该棋盘为一个特殊棋盘.显然特殊方格在棋盘上出现的位置有4^k种情形.因而对任何k≥0,有4^k种不同的特殊棋盘.
下图–图(1)中的特殊棋盘是当k=3时16个特殊棋盘中的一个:
图(1)
题目要求在棋盘覆盖问题中,要用下图-图(2)所示的4种不同形态的L型骨牌覆盖一个给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖.
容易忽视的地方:棋盘分割以后,坐标会发生改变,所以要记录棋盘左上角的方格坐标以推得其他信息
注意的地方 :递归函数单次完成的任务:判断表格的左上角是不是特殊坐标 ,是则继续递归,不是,则覆盖表格的左上角的右下角,然后递归
判断表格的右上角是不是特殊坐标 ,是则继续递归,不是,则覆盖表格的右上角的左下角,然后递归
判断表格的左下角是不是特殊坐标 ,是则继续递归,不是,则覆盖表格的左下角的右上角,然后递归
判断表格的右下角是不是特殊坐标 ,是则继续递归,不是,则覆盖表格的左上角的左上角,然后递归
(递归的意思是 选定好初始值,然后继续执行这个函数,在单次完成时,不用关心)
所以递归函数有两个部分:一个部分是单次函数功能实现的部分(是特殊位置,不处理,不是特殊位置,为特定的点赋值)
一个是上一个函数递推到下一个函数的部分( 继续递归)
所以说,继续递归出现的位置非常重要。
什么时候 继续递归? 分治的时候,分割的时候,由大问题过渡到小问题的时候,(比如找到特殊位置的时候,这时候我们已经做完了对大表的操作,接下来的操作是分割棋盘,所以继续递归)
判断该递归是不是符合要求,就看它能不能解决第一次的分治,由于分治的小问题与大问题解法相同,所以接下来递归只要保证初始值不出错。
//棋盘覆盖问题 /* (tr,tc)是棋盘左上角的方格坐标 (dr,dc)是特殊方格所在的坐标 size是棋盘的行数和列数 */ #include<iostream> using namespace std; int board[1025][1025]; static int tile = 1; void ChessBoard(int tr,int tc,int dr,int dc,int size) { if(size==1) return ;//递归边界 int t=tile++;//L型骨牌号,t是骨牌的值,一个值代表一个骨牌 int s=size/2;//分割棋盘,s是分割后1/4正方形的边长 //覆盖左上角子棋盘 if(dr<tr+s && dc<tc+s) //判断坐标的通式 ChessBoard(tr,tc,dr,dc,s);//特殊方格在此棋盘中 else //此棋盘中无特殊方格,用t号L型骨牌覆盖右下角 { 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 //此棋盘中无特殊方格,用t号L型骨牌覆盖左下角 { board[tr+s-1][tc+s]=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 //此棋盘中无特殊方格,用t号L型骨牌覆盖右上角 { board[tr+s][tc+s-1]=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 //此棋盘中无特殊方格,用t号L型骨牌覆盖左上角 { board[tr+s][tc+s]=t; //覆盖其余方格 ChessBoard(tr+s,tc+s,tr+s,tc+s,s); } } int main() { int i,j; int k; while(cin>>k) { int size = 1<<k; int x,y; cin>>x>>y; board[x][y]=0; ChessBoard(0, 0, x, y, size); for(i=0; i<size; i++) { for(j = 0; j < size; j++) cout<< board[i][j]<<"\\t"; cout<<"\\n"; } } return 0; }
- //棋盘覆盖问题
- /*
- (tr,tc)是棋盘左上角的方格坐标
- (dr,dc)是特殊方格所在的坐标
- size是棋盘的行数和列数
- */
以上是关于分治与递归-棋盘覆盖问题的主要内容,如果未能解决你的问题,请参考以下文章