拒绝白嫖,白嫖有罪,点个赞再走呗
问题描述
在一个由2^k * 2^k个方格组成的棋盘中,若恰有一个方格与其他方格不同,称该方格为特殊方格,且称该棋盘为特殊棋盘。显然,特殊方格在棋盘中出现的位置有 4^k种不同的棋盘。我们要用3个方格组成的L型的方块将整个棋盘覆盖掉。
思路
首先,我们先考虑22的棋盘,无论特殊方格在哪,另外三个就是一个L型的方块,刚好将整个格棋盘覆盖掉。接下来我们考虑44的棋盘,我们首先将其分为四个22的棋盘,特殊方格必定在其中一个棋盘中,则这个棋盘就是22的棋盘的解决方案,另外三个棋盘,我们各取一个角当做一个L型,剩下的,我想你们也都会了。如下图
最终变成了
同理88的棋盘的时候,我们首先将棋盘分为4个4**4的棋盘,其中一个棋盘就是上述44棋盘的解法,另外3个我们继续去一个角,组成L型的方块。如下图
然后将每一个4*4的方格都解出来就可以了
实现
我们首先就是要构造棋盘,我们用的是二维数组来代替棋盘,我们用同一种数字代表L型的方块
打印整个棋盘
public void Println(int a[][]){
for (int i=0;i<a.length;i++){
for (int j=0;j<a[i].length;j++){
System.out.printf("%d\t",a[i][j]);
}
System.out.println("");
}
}
基本的算法
public void ChessBoard(int tr,int tc,int dr,int dc,int size) {//dc:列,dr:行,为特殊方格的位置
if (size == 1)
return;
int t = tile++;
int s = size / 2;
if (dr < tr + s && dc < tc + s) {//特殊方格在左上角,若果不在左上角的棋盘上,就将左上角的右下角的方块当做特殊方块。
ChessBoard(tr, tc, dr, dc, s);
} else {
a[tr + s - 1][tc + s - 1] = t;
ChessBoard(tr, tc, tr + s - 1, tc + s - 1, s);
}
if (dc >= tc + s && dr < tr + s) {//特殊方格在右上角
ChessBoard(tr, tc + s, dr, dc, s);
} else {
a[tr + s - 1][tc + s] = t;
ChessBoard(tr, tc + s, tr + s - 1, tc + s, s);
}
if (dc < tc + s && dr >= tr + s) {//特殊方格在左下角
ChessBoard(tr + s, tc, dr, dc, s);
} else {
a[tr + s][tc + s - 1] = t;
ChessBoard(tr + s, tc, tr + s, tc + s - 1, s);
}
if (dc >= tc + s && dr >= tr + s) {//特殊方格在右下角
ChessBoard(tr + s, tc + s, dr, dc, s);
} else {
a[tr + s][tc + s] = t;
ChessBoard(tr + s, tc + s, tr + s, tc + s, s);
}
}
测试
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n,i,j;
System.out.println("请输入方格为多大,和特殊方格的坐标,例如16 2 3");
n = in.nextInt();
i = in.nextInt();
j = in.nextInt();
Main yyp = new Main();
yyp.a = new int[n][n];
yyp.ChessBoard(0,0,i-1,j-1,n);
yyp.Println(yyp.a);
}
全部代码
package suanfa.cover;
import java.util.Scanner;
public class Main {
int a[][];
private int tile = 1;
public void ChessBoard(int tr,int tc,int dr,int dc,int size) {//dc:列,dr:行,为特殊方格的位置
if (size == 1)
return;
int t = tile++;
int s = size / 2;
if (dr < tr + s && dc < tc + s) {//特殊方格在左上角
ChessBoard(tr, tc, dr, dc, s);
} else {
a[tr + s - 1][tc + s - 1] = t;
ChessBoard(tr, tc, tr + s - 1, tc + s - 1, s);
}
if (dc >= tc + s && dr < tr + s) {//特殊方格在右上角
ChessBoard(tr, tc + s, dr, dc, s);
} else {
a[tr + s - 1][tc + s] = t;
ChessBoard(tr, tc + s, tr + s - 1, tc + s, s);
}
if (dc < tc + s && dr >= tr + s) {//特殊方格在左下角
ChessBoard(tr + s, tc, dr, dc, s);
} else {
a[tr + s][tc + s - 1] = t;
ChessBoard(tr + s, tc, tr + s, tc + s - 1, s);
}
if (dc >= tc + s && dr >= tr + s) {//特殊方格在右下角
ChessBoard(tr + s, tc + s, dr, dc, s);
} else {
a[tr + s][tc + s] = t;
ChessBoard(tr + s, tc + s, tr + s, tc + s, s);
}
}
public void Println(int a[][]){
for (int i=0;i<a.length;i++){
for (int j=0;j<a[i].length;j++){
System.out.printf("%d\t",a[i][j]);
}
System.out.println("");
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n,i,j;
System.out.println("请输入方格为多大,和特殊方格的坐标,例如16 2 3");
n = in.nextInt();
i = in.nextInt();
j = in.nextInt();
Main yyp = new Main();
yyp.a = new int[n][n];
yyp.ChessBoard(0,0,i-1,j-1,n);
yyp.Println(yyp.a);
}
}