递归与分治之棋盘覆盖

《计算机算法设计与分析》第三版递归与分治章节中有一类棋盘覆盖问题。

在一个2^k * 2^k个方格组成的棋盘中,若恰好有一个方格与其他方格不同,则称该方格为一个特殊方格,显然在特殊方格在棋盘上出现的为止有4^k种情形。因而对任何k>=0,有4^k种不同的特殊棋盘。

《递归与分治之棋盘覆盖》                                                      《递归与分治之棋盘覆盖》

有上图四种不同形态的L型骨牌覆盖一个给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。易知在任何一个2^k * 2^k的棋盘覆盖中,用到的L型骨牌个数恰好为(4^k – 1)/3。

 实现的基本原理是将2^k * 2^k的棋盘分成四块2^(k – 1) * 2^(k – 1)的子棋盘,特殊方格一定在其中的一个子棋盘中,如果特殊方格在某一个子棋盘中,继续递归处理这个子棋盘,直到这个子棋盘中只有一个方格为止如果特殊方 格不在某一个子棋盘中,将这个子棋盘中的相应的位置设为骨牌号,将这个无特殊方格的了棋盘转换为有特殊方格的子棋盘,然后再递归处理这个子棋盘。

《递归与分治之棋盘覆盖》

以下是实现的源代码,可能递归起来比较复杂,我在上面做了详细的注释,可以设置八个断点,根据断点一步一步进行调试就行了。

#include <iostream>
#include <string>
using namespace std;

int board[32][32];
//tr,tc每个被分方格的左上角那个
//dr,dc每个被分方格的特殊位置
//刚开始方格的特殊位置 
void chessBoard(int tr,int tc,int dr,int dc,int size)
{
	if( size == 1 )
		return ;
	int half_size ;
	static int num=1;
    int t=num++;
    half_size = size /2 ;
    
	//left up 
    if( dr<tr+half_size && dc < tc+half_size )             //特殊方格在左上角子棋盘
    	chessBoard(tr, tc, dr, dc, half_size);  //如果在左上方,则不需要改变tr,tc起始点的为止0 ,0 。设置短点 
    	
   	else 
   	{                                                  //设置断点 
		board[tr+half_size-1][tc+half_size-1]=t;
		chessBoard(tr, tc, tr+half_size-1, tc+half_size-1, half_size);
   	}
   	
   	//right up         //特殊方格在右上角子棋盘
   	if( dr<tr+half_size && dc>=tc+half_size )
   		chessBoard(tr, tc+half_size, dr, dc, half_size);  //如果在右上方则需要改变tr,tc的位置,移动到tr,tc+half_size。 设置短点 
	
	else                // 不在此棋盘,将此棋盘右下角设为相应的骨牌号
	{                               //设置断点 
		board[tr+half_size-1][tc+half_size] = t;
		chessBoard(tr, tc+half_size, tr+half_size-1, tc+half_size, half_size);      //tr,tc的位置也要同时改变 
	}
	
	//left down
	if( dr>=tr+half_size && dc<tc+half_size )
		chessBoard(tr+half_size, tc, dr, dc, half_size);                 //设置断点 
	else
	{
		board[tr+half_size][tc+half_size-1] = t;                   //设置短点 
		chessBoard(tr+half_size, tc, tr+half_size, tc+half_size-1, half_size);          //tr,tc的位置也要同时改变
	}
	
	//right down
	if(dr>=tr+half_size && dc>=tc+half_size )
		chessBoard(tr+half_size, tc+half_size, dr, dc, half_size);      //设置短点 
	else
	{
		board[tr+half_size][tc+half_size] = t;						//设置短点 
		chessBoard(tr+half_size, tc+half_size, tr+half_size, tc+half_size, half_size);       //tr,tc的位置也要同时改变
	}
}

int main()
{
	int size;
	cout<<"输入方格的大小,必须是2的n的幂"<<endl;
	cin>>size;
	int x,y;
	cout<<"输入特殊方格的位置:"<<endl;
	cin>>x>>y;
	
	memset(board,0,sizeof( board[size][size]) );
	
	chessBoard(0,0,x,y,size);
	
	for(int i=0;i<size;i++)
	{
		for(int j=0;j<size;j++)
			cout<<board[i][j]<<" ";
			
		cout<<endl;
	}
	return 1;
		
}

下面是结果截图,可以用这个简单的数据进行调试:

《递归与分治之棋盘覆盖》

    原文作者:递归与分治算法
    原文地址: https://blog.csdn.net/kejie1235/article/details/8160943
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞