棋盘覆盖

问题描述

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

2.思路

1.当k>0时,将2k*2k棋盘分割为4个2(k-1)*2(k-1)子棋盘

2.将这三个无特殊方格的子棋盘转换为特殊棋盘,用一个L型骨盘覆盖这三个较小棋盘的会和处

3.递归地使用这种分割方法,直至棋盘简化为1*1棋盘,就结束递归。

3.注意

1.每次都对分割后的四个小棋盘进行判断,判断特殊方格是否在里面。

这里的判断的方法是每次先记录下整个大棋盘的左上角方格的行列坐标,然后再与特殊方格坐标进行比较,就可以知道特殊方格是否在该块棋盘中。

  1. 如果特殊方块在里面,这直接递归下去求即可,
  2. 如果不在,这根据分割的四个棋盘的不同位置,把右下角、左下角、右上角或者左上角的方格标记为特殊方块,然后继续递归。在递归函数里,还要有一个变量s来记录边的方格数,每次对棋盘进行划分时,边的方格数都会减半,这个变量是为了方便判断特殊方格的位置。

左上角方格的行列坐标是确定的,根据棋盘的大小和要判断在哪个区域确定

实现细节:

用4*4的棋盘举例

要判断特殊的方格在哪一个区域:

根据传入的参数size,leftRow,leftCol可以将棋盘划分为四个区域,然后和特殊点比较

1. 左上角:`specialRow < leftRow+size && specialCol < leftCol+size`
2. 右上角:`specialRow < leftRow+size && specialCol >= leftCol+size`
3. 左下角:`specialRow >= leftRow+size && specialCol < leftCol+size`
4. 右下角:`specialRow >= leftRow+size && specialCol >= leftCol+size`

填充的特殊点也可以用这几个参数来确定

​ 如果特殊点不在左上角,填充的特殊点在该区域的右下角leftRow+size-1,leftRol+size-1

​ 如果特殊点不在右上角,填充的特殊点在该区域的左下角leftRow+size-1,leftRol+size

​ 如果特殊点不在左下角,填充的特殊点在该区域的右上角leftRow+size,leftCol+size-1

​ 如果特殊点不在右下角,填充的特殊点在该区域的左下角leftRow+size,leftCol+size

2.递归的结束条件

  1. size为1时
//大小为1时,结束递归
if (1 == size) {
return;
}
  1. size为2时
//大小为2时,结束递归
if(size == 2){
number++;
if(specialCol != leftCol || specialRow != leftRow)
board[leftRow][leftCol] = number;
if(specialCol != leftCol+1 || specialRow != leftRow+1)
board[leftRow+1][leftCol+1] = number;
if(specialCol != leftCol+1 || specialRow != leftRow)
board[leftRow][leftCol+1] = number;
if(specialCol != leftCol || specialRow != leftRow+1)
board[leftRow+1][leftCol] = number;
return;
}

4.代码

package com.java.test;

public class ChessProblem {

    int size;//容量
int[][] board;//棋盘
int specialRow;//特殊点横坐标
static int number = 0;//L形编号,这个一定要是静态的,可以在任何地方访问到
int specialCol;//特殊点纵坐标 public ChessProblem(int specialRow, int specialCol, int size) {
this.size = size;
this.specialCol = specialCol;
this.specialRow = specialRow;
board = new int[size][size];
} //specialRow 特殊点的行下标
//specialCol 特殊点的列下标
//leftRow 矩阵的左边起点行下标
//leftCol 矩阵左边起点的列下标
//size 棋盘的宽或者高 public void setBoard(int specialRow, int specialCol, int leftRow, int leftCol, int size) {
//大小为1时,结束递归
if (1 == size) {
return;
} int subSize = size / 2;
number++;
int n = number;//注意这里一定要吧number存在当前的递归层次里,否则进入下一层递归全局变量会发生改变 //假设特殊点在左上角区域
if (specialRow < leftRow + subSize && specialCol < leftCol + subSize) {
setBoard(specialRow, specialCol, leftRow, leftCol, subSize);
}
else {
//不在左上角,设左上角矩阵的右下角就是特殊点(和别的一起放置L形)
board[leftRow + subSize - 1][leftCol + subSize - 1] = n;
setBoard(leftRow + subSize - 1, leftCol + subSize - 1, leftRow, leftCol, subSize);
} //假设特殊点在右上方
if (specialRow < leftRow + subSize && specialCol >= leftCol + subSize) {
setBoard(specialRow, specialCol, leftRow, leftCol + subSize, subSize);
}
else {
//不在右上方,设右上方矩阵的左下角就是特殊点(和别的一起放置L形)
board[leftRow + subSize -1][leftCol + subSize] = n;
setBoard(leftRow + subSize -1, leftCol + subSize, leftRow, leftCol + subSize, subSize);
} //特殊点在左下方
if (specialRow >= leftRow + subSize && specialCol < leftCol + subSize) {
setBoard(specialRow, specialCol, leftRow + subSize, leftCol, subSize);
}
else {
//不在左下方,设左下方矩阵的右上角就是特殊点(和别的一起放置L形)
board[leftRow + subSize][leftCol + subSize - 1] = n;
setBoard(leftRow + subSize, leftCol + subSize - 1, leftRow + subSize, leftCol, subSize);
} //特殊点在右下角
if (specialRow >= leftRow + subSize && specialCol >= leftCol + subSize) {
setBoard(specialRow, specialCol, leftRow + subSize, leftCol + subSize, subSize);
}
else {
//不在右下角,设右下角矩阵的左上就是特殊点(和别的一起放置L形)
board[leftRow + subSize][leftCol + subSize] = n;
setBoard(leftRow + subSize, leftCol + subSize, leftRow + subSize, leftCol + subSize, subSize);
}
} //输出棋盘
public void printBoard(int specialRow,int specialCol,int size) {
setBoard(specialRow, specialCol, 0, 0, size);
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
System.out.print(board[i][j] + "\t");
}
System.out.println();
}
} public static void main(String[] args) {
//棋盘的大小
int N = 8;
//特殊点的坐标
int specialRow = 0;
int specialCol = 1;
ChessProblem chessProblem = new ChessProblem(specialRow , specialCol , N);
chessProblem.printBoard(specialRow, specialCol, N);
} }

5.运行截图

棋盘覆盖(java实现)的更多相关文章

  1. 递归与分治策略之棋盘覆盖Java实现

    递归与分治策略之棋盘覆盖 一.问题描述 二.过程详解 1.棋盘如下图,其中有一特殊方格:16*16 . 2.第一个分割结果:8*8 3.第二次分割结果:4*4 4.第三次分割结果:2*2 5.第四次分 ...

  2. 棋盘覆盖(大数阶乘,大数相除 + java)

    棋盘覆盖 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 在一个2k×2k(1<=k<=100)的棋盘中恰有一方格被覆盖,如图1(k=2时),现用一缺角的 ...

  3. 棋盘覆盖问题(算法分析)(Java版)

    1.问题描述: 在一个2k×2k个方格组成的棋盘中,若有一个方格与其他方格不同,则称该方格为一特殊方格,且称该棋盘为一个特殊棋盘.显然特殊方格在棋盘上出现的位置有种情形.因而对任何 k≥0,有4k种不 ...

  4. NYOJ 45 棋盘覆盖

    棋盘覆盖 水题,题不难,找公式难 import java.math.BigInteger; import java.util.Scanner; public class Main { public s ...

  5. bzoj 2706: [SDOI2012]棋盘覆盖 Dancing Link

    2706: [SDOI2012]棋盘覆盖 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 255  Solved: 77[Submit][Status] ...

  6. NYOJ 45 棋盘覆盖 模拟+高精度

    题意就不说了,中文题... 小白上讲了棋盘覆盖,于是我就挖了这题来做. 棋盘覆盖的推导不是很难理解,就是分治的思想,具体可以去谷歌下. 公式就是f(k) = f(k - 1) * 4 + 1,再化解下 ...

  7. 棋盘覆盖(一) ACM

    棋盘覆盖 描述 在一个2k×2k(1<=k<=100)的棋盘中恰有一方格被覆盖,如图1(k=2时),现用一缺角的2×2方格(图2为其中缺右下角的一个),去覆盖2k×2k未被覆盖过的方格,求 ...

  8. CODEVS 2171 棋盘覆盖

    2171 棋盘覆盖 给出一张nn(n<=100)的国际象棋棋盘,其中被删除了一些点,问可以使用多少12的多米诺骨牌进行掩盖. 错误日志: 直接在模板上调整 \(maxn\) 时没有在相应邻接表数 ...

  9. JavaScript编写棋盘覆盖

    一.前言 之前做了一个算法作业,叫做棋盘覆盖,本来需要用c语言来编写的,但是因为我的c语言是半桶水(哈哈),所以索性就把网上的c语言写法改成JavaScript写法,并且把它的覆盖效果显示出来 二.关 ...

  10. TYVJ 1035 / codevs 2171 棋盘覆盖

    Problem Description 给定一个n * m的棋盘,已知某些各自禁止放置,求最多往棋盘上放多少长度为2宽度为1的骨牌(骨牌不重叠) Input 第一行为n,m(表示有m个删除的格子)第二 ...

随机推荐

  1. Html飞机大战(八):子弹的移动和管理

    好家伙,这应该是这个小游戏最难的几个点之一了 现在我们要做出子弹射击的效果我们应该如何处理? 1.首先我们要确定几个变量和方法的关系 变量: 子弹  bullet  弹夹(用来装子弹的东西)bulle ...

  2. SQL Server事务隔离级别

    事务 定义 事务是作为单个逻辑工作单元执行的一系列操作. 一个逻辑工作单元必须有四个属性,称为原子性.一致性.隔离性和持久性 (ACID) 属性,只有这样才能成为一个事务. 一个事务可以包含多个操作. ...

  3. KingbaseES 与 Oracle 用户口令管理与资源管理

    一.概述 KingbaseES可以对用户口令与用户占用资源进行必要的管理.其管理方式,在这里与Oracle数据库进行参考比较. KingbaseES 使用扩展插件建立的系统参数,这组参数可以对数据库资 ...

  4. Currtid 函数与性能问题

    对于Oracle ,一条tuple 的 rowid正常是不会变化的(引发row movement的操作除外,如:跨分区迁移update,表收缩),因此,应用设计上可以方便的使用rowid,加快访问速度 ...

  5. 【Vue学习笔记】—— vuex的语法 { }

    学习笔记 作者:o_Ming vuex Vuex ++ state ++ (用于存储全局数据) 组件访问 state 中的全局数据的方式1: this.$store.state.全局数据 组件访问 s ...

  6. 分布式链路追踪体验-skywalking入门使用

    背景 旁友,你的线上服务是不是偶尔来个超时,或者突然抖动一下,造成用户一堆反馈投诉.然后你费了九牛二虎之力,查了一圈圈代码和日志才总算定位到问题原因了.或者公司内部有链路追踪系统,虽然可以很轻松地通过 ...

  7. ESX添加过时的硬件

    昨天遇到了个ESX上有旧的qlogic的FC卡无法识别的问题.无法识别也就无法连接存储,整个ESX就基本无法使用了.所以,需要检查硬件.一开始,在查了很多资料各种命令检查,走了很多弯路.这里我总结一下 ...

  8. Linux使用密钥登录SSH

    输入命令和上传密钥时需要注意当前目录.账号和读写权限 生成密钥 使用服务器生成(方法一,推荐) 1.1生成密钥 #ssh-keygen(这里pwd为当前账号的home目录) 1.2下载密钥 .id_r ...

  9. JAVA中容器设计的进化史:从白盒到黑盒,再到跻身为设计模式之一的迭代器

    大家好,又见面了. 在我们的项目编码中,不可避免的会用到一些容器类,我们可以直接使用List.Map.Set.Array等类型.当然,为了体现业务层面的含义,我们也会根据实际需要自行封装一些专门的Be ...

  10. 关于Loki中promtail组件收集日志的几点思考

    promtail组件是采用docker方式运行的,配置文件也是在docker容器中,宿主机中没有挂载点,这就有问题了. 宿主机中没有挂载配置文件,也就没法修改,登录promtail的docker容器中 ...