java 实现棋盘覆盖问题

  • 问题描述:在一个2k*2k的棋盘中,有一个特殊方格,要求用L型骨牌覆盖满除特殊方格外的所有其他方格,且骨牌不得重叠.(骨牌可以旋转放置)
  • 输入:棋盘的边长、特殊方格坐标
  • 输出:骨牌放法.其中用0表示特殊方格,同一张骨牌所占方格用同一个数字表示,不同骨牌用不同数字.

 解题思想:

采用分治法解决该问题。分治法是把一个规模很大的问题分解为多个规模较小、类似的子问题,然后递归地解决所有子问题,最后再由子问题的解决得到原问题的解决。

所以将2k*2k的棋盘,先分成相等的四块子棋盘,其中特殊方格位于四个中的一个,构造剩下没特殊方格三个子棋盘:将一块骨牌放在这三个小棋盘的交界处,使骨牌的每一个方格都作为三个小棋盘的特殊方格,骨牌具体放法如下:

  • 左上的子棋盘若不存在特殊方格,将该子棋盘右下角的那个方格覆盖为特殊方格
  • 右上的子棋盘若不存在特殊方格,将该子棋盘左下角的那个方格覆盖为特殊方格
  • 左下的子棋盘若不存在特殊方格,将该子棋盘右上角的那个方格覆盖为特殊方格
  • 右下的子棋盘若不存在特殊方格,将该子棋盘左上角的那个方格覆盖为特殊方格 至此,每个小棋盘都有一个特殊方格,然后递归调用,就可以解决问题了。
public class Chess {
 
 /**  棋盘的规格  */
 public static int SIZE = 8;
 /**  特殊格子的竖坐标(从零开始)  */
 public static int TR = 1;
 /**  特殊格子的横坐标(从零开始)  */
 public static int TC = 1;

 /** 模拟棋盘  */
 static int[][] board;
 /** 模拟骨牌(相同数字为同一块骨牌)  */
 static int tile = 1;

 /**
  * 棋盘覆盖问题
  * @param dr  左上角方格行号
  * @param dc  左上角方格列号
  * @param tr  特殊方格行号
  * @param tc  特殊方格列号
  * @param size  2的正整数次方
  */
 public static void chessBoard(int dr, int dc, int tr, int tc, int size) {

  if (size == 1) {
   return;
  }

  int t = tile++; 
  /**  分割棋盘后的size  */
  int s = size / 2;

  // 判断特殊方格是否在左上角的小棋盘中
  if (tr < dr + s && tc < dc + s) {
   chessBoard(dr, dc, tr, tc, s);
  } else {
   board[dr + s - 1][dc + s - 1] = t;
   chessBoard(dr, dc, dr + s - 1, dc + s - 1, s);
  }

  // 判断特殊方格是否在右上角的小棋盘中
  if (tr < dr + s && tc >= dc + s) {
   chessBoard(dr, dc + s, tr, tc, s);
  } else {
   board[dr + s - 1][dc + s] = t;
   chessBoard(dr, dc + s, dr + s - 1, dc + s, s);
  }

  // 判断特殊方格是否在左下角的小棋盘中
  if (tr >= dr + s && tc < dc + s) {
   chessBoard(dr + s, dc, tr, tc, s);
  } else {
   board[dr + s][dc + s - 1] = t;
   chessBoard(dr + s, dc, dr + s, dc + s - 1, s);
  }

  // 判断特殊方格是否在youxia角的小棋盘中
  if (tr >= dr + s && tc >= dc + s) {
   chessBoard(dr + s, dc + s, tr, tc, s);
  } else {
   board[dr + s][dc + s] = t;
   chessBoard(dr + s, dc + s, dr + s, dc + s, s);
  }
 }

 public static void main(String[] args) {
  
  // init parameter
  try{
   if(args[0]!=null){
    SIZE = Integer.parseInt(args[0], 10);
   }
   if(args[1]!=null){
    TR = Integer.parseInt(args[1], 10);
   }
   if(args[2]!=null){
    TC = Integer.parseInt(args[2], 10);
   }
  }catch(Exception e){
   System.out.print("\t(部分)采用默认参数");
  }
  
  System.out.printf("\t棋盘规模:%d*%d",SIZE,SIZE);
  System.out.printf("\t特殊方格:(%d,%d)",TR,TC);
  
  // 初始化棋盘
  board = new int[SIZE][SIZE];
  // 调用方法进行测试
  chessBoard(0, 0, TR, TC, SIZE);
  // 显示棋盘结果
  for (int[] is : board) {
   System.out.println();
   for (int i : is) {
    System.out.printf("%4d", i);
   }
  }
 }
}

效果截图:

算法复杂性分析:

设T(k)是此算法所需的时间,则根据分治法可知:

解此递归方程可得,T(k)=O(4k)。由于覆盖2k*2k的棋盘所需的骨牌个数为(4k-1)/3,所以此算法是一个渐进意义下最优算法。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏锦小年的博客

复杂网络(2)--图论的基本理论-最小生成树问题

连通且不含圈的无向图称为树(tree)。树中度为1的节点称为树叶,度大于1的节点称为分支点。 若图G=(V,E)的生成子图是一棵树,则称该树为图G的生成树(...

3246
来自专栏Petrichor的专栏

tensorflow: bn层

可视化 batch normalization 过程中的 tensor演化(以输入一张[1, 4 , 4, 1]的图片为例)

2964
来自专栏人工智能

十五:多层感知机与布尔函数

今天没有别的话,好好学习,多多转发! 本期内容是 【多层感知机与布尔函数】 场景描述 神经网络概念的诞生很大程度上受到了神经科学的启发。生物学研究表明,大脑皮层...

2758
来自专栏小小挖掘机

使用Seq2Seq+attention实现简单的Chatbot

本文代码的github连接:https://github.com/princewen/tensorflow_practice/tree/master/chat_...

2.9K6
来自专栏来自地球男人的部落格

Seq2Seq模型

前言: 此文翻译自TensorFlow tutorial: Sequence-to-Sequence Models 本文的尽量在做到意思正确的情况下,做到不...

30710
来自专栏人工智能LeadAI

决策树会有哪些特性?

决策树(Decision Tree)是机器学习中最常见的算法, 因为决策树的结果简单,容易理解, 因此应用超级广泛, 但是机器学习的专家们在设计决策树的时候会考...

3377
来自专栏ml

数据挖掘之聚类算法K-Means总结

序   由于项目需要,需要对数据进行处理,故而又要滚回来看看paper,做点小功课,这篇文章只是简单的总结一下基础的Kmeans算法思想以及实现; 正文:   ...

3818
来自专栏人工智能

人工智能AI(5):线性代数之矩阵、线性空间

在前面的篇幅中,我们简单的介绍过矩阵的定义,按照原计划本来,今天准备写特征分解以及奇异值分解,但是发现这其中涉及到比较多的矩阵相关的知识,所以在讨论这些问题之前...

2505
来自专栏小鹏的专栏

Tensorflow使用的预训练的resnet_v2_50,resnet_v2_101,resnet_v2_152等模型预测,训练

tensorflow 实现:Inception,ResNet , VGG , MobileNet, Inception-ResNet; 地址: https:/...

9538
来自专栏yw的数据分析

gplots heatmap.2和ggplot2 geom_tile实现数据聚类和热图plot

主要步骤 ggplot2 数据处理成矩阵形式,给行名列名 hclust聚类,改变矩阵行列顺序为聚类后的顺序 melt数据,处理成ggplot2能够直接处理的数据...

4447

扫码关注云+社区