分治法--棋盘覆盖问题

前几天学分治算法的时候碰到了一个经典的棋盘覆盖问题,现在小周周就来总结一下解题的过程吧,加强我们对分治算法的理解。

棋盘覆盖问题

问题描述:在一个2的K次方乘以2的K次方方格组成的棋盘中,一开始恰有一个方格与其他方格不一样,则称这个方格为特殊方格。我们要把整个棋盘覆盖掉。为了解决这个棘手的问题,我们想到了用一个L型骨牌去覆盖其他三个没有特殊方格的子棋盘。
例如下图b,那个红色的方格就是特殊方格,为了能够递归解决这样相同的子问题,我们就要用一个L型骨牌去填充另外三个没有特殊方格的子棋盘,而且是填充那三个子棋盘的交界处,如下图黄色区域部分。,这样我们就能够使得全部子棋盘都有一个特殊方格,然后就可以递归解决。分治法--棋盘覆盖问题_第1张图片

算法分析

如果特殊方格在左上角子棋盘中,我们则递归填充左上角子棋盘,否则,如果特殊方格不在左上角子棋盘,就用t号骨牌覆盖左上角子棋盘的右下角,将右下角看做特殊方格,递归覆盖左上角子棋盘的其余方格。
如果特殊方格在右上角子棋盘中,我们则递归填充右上角子棋盘,否则,如果特殊方格不在右上角子棋盘,就用t号骨牌覆盖右上角子棋盘的左下角,将左下角看做特殊方格,递归覆盖右上角子棋盘的其余方格。
如果特殊方格在左下角子棋盘中,我们则递归填充左下角子棋盘,否则,如果特殊方格不在左下角子棋盘,就用t号骨牌覆盖左下角子棋盘的右上角,将右上角看做特殊方格,递归覆盖左下角子棋盘的其余方格。
如果特殊方格在右下角子棋盘中,我们则递归填充右下角子棋盘,否则,如果特殊方格不在右下角子棋盘,就用t号骨牌覆盖右下角子棋盘的左上角,将左上角看做特殊方格,递归覆盖右下角子棋盘的其余方格。
当每个子棋盘只剩下一个方格的时候,就是我们的递归出口了。子问题就是容易解决的了。这也是我们分治法的思想所在。

代码如下所示(java)

import java.util.Scanner;
public class Chair {
     
	static int title=0; //L型骨牌编号
	static int [][]Board=new int[8][8];   //二维数组棋盘
	public static void main(String[] args) {
     
		Scanner s=new Scanner(System.in);
		System.out.println("请输入初始的特殊方格位置:");
		int x=s.nextInt();
		int y=s.nextInt();
		ChessBoard(0,0,x,y,8);  //调用覆盖方法
		System.out.println("棋盘覆盖的结果如下:");
		for(int i=0;i<8;i++) {
     
			for(int j=0;j<8;j++) {
     
				System.out.print(Board[i][j]+"\t");
			}
			System.out.println();
		}
	}
	public static void ChessBoard(int lh,int ll,int sh,int sl,int size) {
     
		if(size==1)  //递归出口 方格数为1
			return;
		int t=title++;  //t是骨牌号
		int s=size/2;   //棋盘规格
		if(sh<lh+s&&sl<ll+s) {
       //特殊方格在左上角子棋盘中
			ChessBoard(lh,ll,sh,sl,s); //递归填充左上角子棋盘
		}else {
     					//特殊方格不在左上角子棋盘
			Board[lh+s-1][ll+s-1]=t;  //用t号骨牌覆盖左上角子棋盘的右下角
			ChessBoard(lh,ll,lh+s-1,ll+s-1,s);//将右下角看做特殊方格,递归覆盖左上角子棋盘的其余方格
		}
		if(sh<lh+s&&sl>=ll+s) {
      //特殊方格在右上角子棋盘
			ChessBoard(lh,ll+s,sh,sl,s);//递归覆盖右上角子棋盘
		}else {
     				//特殊方格不在右上角棋盘
			Board[lh+s-1][ll+s]=t; //用t号骨牌覆盖右上角子棋盘的左下角
			ChessBoard(lh,ll+s,lh+s-1,ll+s,s); //将左下角看做特殊方格,递归覆盖右上角子棋盘的其余方格
		}
		if(sh>=lh+s&&sl<ll+s) {
       //特殊方格在左下角子棋盘
			ChessBoard(lh+s,ll,sh,sl,s);  //递归覆盖左下角子棋盘
		}else {
      					//特殊方格不在左下角子棋盘
			Board[lh+s][ll+s-1]=t; //用t号骨牌覆盖左下角子棋盘的右上角
			ChessBoard(lh+s,ll,lh+s,ll+s-1,s); //将右上角看做特殊方格,递归覆盖左下角子棋盘的其余方格
		}
		if(sh>=lh+s&&sl>=ll+s) {
       //特殊方格在右下角子棋盘
			ChessBoard(lh+s,ll+s,sh,sl,s);  //递归覆盖右下角子棋盘
		}else {
     				//特殊方格不在右下角
			Board[lh+s][ll+s]=t;  //用t号骨牌覆盖右下角子棋盘的左上角
			ChessBoard(lh+s,ll+s,lh+s,ll+s,s);	//将左上角看做特殊方格,递归覆盖右下角子棋盘的其余方格
		}
	}
}

运行结果如下图所示

测试数据 一开始特殊方格为坐标(3,5)
分治法--棋盘覆盖问题_第2张图片
好啦 棋盘覆盖问题我们就分析到这里啦,如果有什么不懂的记得留言交流或者私信小周周呀!
还是老规矩,如果你觉得这篇文章对你有帮助的话,别忘了点个赞哦,小手轻轻 送上爱心。
【无名之辈 我是谁 小小的天 也有大大的梦想】

你可能感兴趣的:(分治算法z,分治算法)