分治法的棋盘覆盖问题(java)
题目要求:要用图2中的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
对于boardfill问题,我的求解算法采用分治原理,将母棋盘按照一定的规则不断划分为4个子棋盘,分治的具体思路和规则如图1所示。划分的过程对应于程序中的
Divide(int[][] a,int L,int U,int R,int D)
方法,
DoAStep(int[][] a,int L,int U,int R,int D)
方法对应于走一步L形棋子。
![图1 分治的具体思路和规则](https://i-blog.csdnimg.cn/blog_migrate/b5721ccdb3329814f73d86019d853e9a.png)
图1 分治的具体思路和规则
程序运行结果如下:特殊棋子标记为1,之后每次的L形棋有三个相同的数字表示,并且该数字表示这个L形棋是第几步落子的。
下面提供java源代码供大家参考学习。
/*
* 作者:泯而好学
* 2018/10/24
* ucas
*/
import java.util.Arrays;
public class BoardFillDemo {
static int step = 2;
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] a = new int[16][16];//棋盘大小的设定
a[2][1] = 1;//特殊棋子的位置
Divide(a,0,0,a.length-1,a.length-1);
for (int i = 0; i < a.length; i++) {
System.out.println(Arrays.toString(a[i]));
}
}
static int sum2dArray(int[][] a,int L,int U,int R,int D) {
int sum = 0;
for(int i = L;i <= R;i++){
for(int j = U;j <= D;j++){
sum+=a[i][j];}
}
return sum;
}
static void DoAStep(int[][] a,int L,int U,int R,int D) {
int midx = L + (R - L)/2;
int midy = U + (D - U)/2;
if(sum2dArray(a,L,U,midx,midy) == 0) {
a[midx][midy] = step;
}
if(sum2dArray(a,midx+1,U,R,midy) == 0) {
a[midx+1][midy] = step;
}
if(sum2dArray(a,L,midy+1,midx,D) == 0) {
a[midx][midy+1] = step;
}
if(sum2dArray(a,midx+1,midy+1,R,D) == 0) {
a[midx+1][midy+1] = step;
}
step ++;
}
static void Divide(int[][] a,int L,int U,int R,int D) {
DoAStep(a,L,U,R,D);
if(R - L > 1) {
int midx = L + (R - L)/2;
int midy = U + (D - U)/2;
Divide(a,L,U,midx,midy);//左上部分
Divide(a,midx+1,U,R,midy);//右上部分
Divide(a,L,midy+1,midx,D);//左下部分
Divide(a,midx+1,midy+1,R,D);//右下部分
}
}
}