您的位置:首页 > 编程语言 > Java开发

Java解决棋盘覆盖问题

2021-01-22 23:03 295 查看

  问题描述:

      在一个2^k×2^k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

      分析:
           该题关键在于如何划分各L型骨牌所在位置区域。我们发现,L型骨牌占三个方格,我们可以把棋盘从中央分为四块,那么这四块子棋盘中仅一块是有特殊方格的,可以用一块骨牌使得其他三块子棋盘均被覆盖。以此为原则,无论这种分法是否最终可解,我们首先保证了每个子棋盘都有一个特殊方格,所以,分治的模型就出来了。
           我们可以用递归来完成分治的任务。每次递归divide(zx,zy,si,x,y),(zx,zy)为子棋盘左上角坐标,si为子棋盘大小,因为棋盘总为正方形,所以si为边长,那么前3个参数就确定了子棋盘的位置和大小;(x,y)表示子棋盘中特殊方格的位置,这个位置是由上层递归分配骨牌后决定的。以此为标准。
递归流程为:
      ①判断边界,若当前棋盘大小为1,则无法再分割,递归结束。
      ②定子棋盘中心位置。
      ③判断特殊方格所在位置(左上,右上,左下,或右下)。
      ④根据特殊方格位置确定所选L型骨牌,原特殊方格和三个L型骨牌的方格分别为四个子棋盘的特殊方格。
      ⑤依据④中判断,按编号填充棋盘。
      ⑥4次递归,分别对应四个子棋盘。
       算法实现:

      (1)棋盘:可以用一个二维数组board[size][size]表示一个棋盘,其中,size=2^k。为了在递归处理的过程中使用同一个棋盘,将数组board设为全局变量;

      (2)子棋盘:整个棋盘用二维数组board[size][size]表示,其中的子棋盘由棋盘左上角的下标tr、tc和棋盘大小s表示;

      (3)特殊方格:用board[dr][dc]表示特殊方格,dr和dc是该特殊方格在二维数组board中的下标;

      (4) L型骨牌:一个2^k×2^k的棋盘中有一个特殊方格,所以,用到L型骨牌的个数为(4^k-1)/3,将所有L型骨牌从1开始连续编号,用一个全局变量t表示。设全局变量t已初始化为0

下面讨论棋盘覆盖问题中数据结构的设计。

(1)棋盘:可以用一个二维数组board[size][size]表示一个棋盘,其中,size=2^k。为了在递归处理的过程中使用同一个棋盘,将数组board设为全局变量;

(2)子棋盘:整个棋盘用二维数组board[size][size]表示,其中的子棋盘由棋盘左上角的下标tr、tc和棋盘大小s表示;

(3)特殊方格:用board[dr][dc]表示特殊方格,dr和dc是该特殊方格在二维数组board中的下标;

(4) L型骨牌:一个2^k×2^k的棋盘中有一个特殊方格,所以,用到L型骨牌的个数为(4^k-1)/3,将所有L型骨牌从1开始连续编号,用一个全局变量t表示。

设全局变量t已初始化为0

下面讨论棋盘覆盖问题中数据结构的设计。

(1)棋盘:可以用一个二维数组board[size][size]表示一个棋盘,其中,size=2^k。为了在递归处理的过程中使用同一个棋盘,将数组board设为全局变量;

(2)子棋盘:整个棋盘用二维数组board[size][size]表示,其中的子棋盘由棋盘左上角的下标tr、tc和棋盘大小s表示;

(3)特殊方格:用board[dr][dc]表示特殊方格,dr和dc是该特殊方格在二维数组board中的下标;

(4) L型骨牌:一个2^k×2^k的棋盘中有一个特殊方格,所以,用到L型骨牌的个数为(4^k-1)/3,将所有L型骨牌从1开始连续编号,用一个全局变量t表示。

设全局变量t已初始化为0.

      程序清单如下:   

package chessboard;

import java.util.Scanner;

/**
 *
 * @author Administrator
 */
public class Chessboard {
    private static int boardsize=8;
    public static int[][] board = new int[boardsize][boardsize];
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        Scanner input = new Scanner(System.in);
        System.out.println("棋盘的大小为"+boardsize);
        int[][] board = new int[boardsize][boardsize];
        System.out.println("特殊块在棋盘中的行号是:");
        int dr = input.nextInt();
        System.out.println("特殊块在棋盘中的列号是:");
        int dc = input.nextInt();
        chessBoard(0,0,dr-1,dc-1,boardsize);
        System.out.println("特殊块在棋盘中的位置是第"+dr+"行第"+dc+"列,覆盖后的棋盘:");
        printboard();
    }
    public static int title = 0;
    public static void chessBoard(int tr, int tc, int dr, int dc, int size)
{
  if (size == 1) return;
  int t = title++,  // L型骨牌号
  s = size/2;  // 分割棋盘
  // 覆盖左上角子棋盘
  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);}
}
     public static void printboard(){
         for(int i=0;i<boardsize;i++){
             for(int j =0;j<boardsize;j++){
                 System.out.print(board[i][j]+"\t");
             }
             System.out.println('\n');
         }
     }

}

      根据提示,输入特殊块的行和列,输出矩阵数组,程序正确运行。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: