目录

题目描述

输入

输出

题目解析

算法代码实现


题目描述

在一个2^k * 2^k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格,且称该棋盘为特殊棋盘。

在棋盘覆盖问题中,要用如下图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

输入

控制台输入

第一行为整数k,(不是棋盘大小是2^k * 2^k,1≤k≤10),

第二行是两个整数,表示特殊方格所在行和列。

3

2 2

输出

特殊方格用0表示,数据间用制表符隔开,要求遍历顺序按从左到右,从上到下。具体看样例

3      3      4      4      8      8      9      9
  3      0      2      4      8      7      7      9
  5      2      2      6    10    10      7    11
  5      5      6      6      1    10    11    11
13    13    14      1      1    18    19    19
13    12    14    14    18    18    17    19
15    12    12    16    20    17    17    21
15    15    16    16    20    20    21    21

题目解析

输入

3

2 2

表示创建一个2³ x 2³ 的棋盘,即 8 x 8 棋盘,该棋盘中有一个特殊方格,其位置在棋盘的第2行,第2列。

按照题目要求,我们可以使用4种不同形态的L型骨牌来覆盖特殊方格(2,2)其外的其他方格,L型骨牌可以用相同的数字来标记,如下图所示:

此题的解题思路采用分治法

假设k=1,则此时棋盘为2x2网格

特殊方格0的位置共有四处可能,如上图所示,

而无论特殊方格位置在哪,我们都可以使用不同形态的L型骨牌填充剩余格子


假设k=2,此时棋盘为4x4网格

特殊方格的放置位置可以有16处,但是特殊方格无论怎么放置,都可以转化如下四种位置(代入旋转,镜像,反转思维看)

因此,我们将4x4棋盘,分解为了4个2x2子棋盘,则特殊方格可以放置在任意一个2x2子棋盘中,并且放置在子棋盘中的位置只有上图所示的四种情况。

则此时,特殊方格所在的子棋盘的剩余网格必然可以被L型骨牌覆盖,如下图所示:

剩下工作就是将剩余的3个2x2的子棋盘用L型骨牌覆盖:

我们已经知道了一个L型骨牌占据三个方格,因此一个2x2的棋盘只能放入一个L型骨牌,并且还剩1个空闲方格。

因此3个2x2棋盘可以放3个L型骨牌,还剩余3个空闲方格。而剩余的3个空闲方格数目刚好符合一个L型骨牌所需要占据的方格数。

因此,我们必须让3个2x2棋盘放完L型骨牌后产生的空闲方格紧挨在一起,这样才能再次凑出一个L型骨牌。

反过来思考,我们可以先将剩余的3个2x2子棋盘的空闲网格位置先确定了,让3个空闲网格形成L型骨牌

因此最终4x4棋盘的覆盖策略如下:

为了保证分治法分解出来的子问题是相同的,我们可以将空闲网格也看成特殊方格。


假设k=3,则此时棋盘为8 x 8的网格

按照之前的思路,我们需要将:

8x8的棋盘,分解为 4个 4x4 的棋盘,则特殊方格0必然在某个4x4棋盘中。

假设,我们找到了包含特殊方格的4x4棋盘,则我们需要继续将4x4棋盘分解为4个 2x2 棋盘,同样的,特殊方格0必然在某个2x2棋盘中。

假设,我们找到了包含特殊方格的2x2棋盘,我们称此2x2棋盘为a棋盘,则a棋盘的覆盖策略已经确定,如下图橙色L型骨牌覆盖。

另外3个2x2棋盘的空闲网格位置也被迫确定了,如下图绿色L型骨牌覆盖。

而3个2x2棋盘的空闲网格位置确定好了,则它们的L型骨牌覆盖策略也就定了。

因此一个4x4棋盘的覆盖策略就被确定了,我们称此4x4棋盘为A棋盘。

通过A棋盘的覆盖,我们发现,一个 2^k * 2^k 的棋盘,放下足够多的L型骨牌后,必然还剩一个空闲网格。比如2x2棋盘只能放下 2x2/3=1...1个,4x4棋盘只能放下4x4/3=5...1,8x8棋盘只能放下8x8/3=21...1。

因此8x8棋盘中除了A棋盘外的剩余3个4x4子棋盘,无论每个4x4棋盘如何放置L型骨牌,自身必然剩余1个空闲网格。则3个4x4棋盘必然还剩3个空闲网格,则此时我们只能将这三个空闲网格凑在一起,形成L型骨牌。

同样地,为了保证分治法分解出来的子问题是相同的,我们可以将空闲网格也看成特殊方格。

因此本题的分解思路应该如下:

  • 将2^k * 2^k棋盘分为4个 2^(k-1) * 2^(k-1)的子棋盘,判断特殊方格位于哪个子棋盘中
  1. 含有特殊方格的子棋盘继续进行分解,直到子棋盘为1x1
  2. 不含有特殊方格的子棋盘,我们人为的为其设定一个特殊方格,即指定它们的空闲方格的为特殊方格。而它们空闲方格的位置,必然是相连的且围绕(含有特殊方格的子棋盘),如下图所示:

算法代码实现

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");const rl = readline.createInterface({input: process.stdin,output: process.stdout,
});const arr = [];
rl.on("line", (line) => {arr.push(line);if (arr.length === 2) { // 让控制台支持多行输入const k = parseInt(arr[0]);const [r, c] = arr[1].split(" ").map((item) => parseInt(item));gridCover(k, r, c).map((row) => {console.log(row.join("\t"));});arr.length = 0; // 让控制台支持不断输入测试}
});/* 棋盘覆盖 */
function gridCover(k, row, col) {// tile是L型骨牌的编号let tile = 1;// 棋盘大小 size x size,而size = 2^klet size = 1 << k;// 创建一个size x size大小的二维数组作为棋盘const grid = createGrid(size, size);// 标记出特殊方格的位置grid[row - 1][col - 1] = 0;// tr表示棋盘左上角的行号,tc表示棋盘左上角的列号,dr表示特殊方格的行号,dc表示特殊方格的列好,size表示棋盘的大小function chessBoard(tr, tc, dr, dc, size) {if (size === 1) return;let t = tile++;let s = size / 2;// 如果特殊方格0位于左上角子棋盘中,则左上角子棋盘为特殊棋盘if (dr < tr + s && dc < tc + s) {// 分解特殊棋盘chessBoard(tr, tc, dr, dc, s);} else {// 否则,左上角子棋盘不是特殊棋盘,我们可以将其空闲方格位置(右下角)定义为特殊方格,让其变为一个特殊棋盘grid[tr + s - 1][tc + s - 1] = t;// 分解特殊棋盘chessBoard(tr, tc, tr + s - 1, tc + s - 1, s);}// 如果特殊方格0位于右上角子棋盘中,则右上角子棋盘为特殊棋盘if (dr < tr + s && dc >= tc + s) {// 分解特殊棋盘chessBoard(tr, tc + s, dr, dc, s);} else {// 否则,右上角子棋盘不是特殊棋盘,我们可以将其空闲方格位置(左下角)定义为特殊方格,让其变为一个特殊棋盘grid[tr + s - 1][tc + s] = t;chessBoard(tr, tc + s, tr + s - 1, tc + s, s);}// 如果特殊方格0位于左下角子棋盘中,则左下角子棋盘为特殊棋盘if (dr >= tr + s && dc < tc + s) {// 分解特殊棋盘chessBoard(tr + s, tc, dr, dc, s);} else {// 否则,左下角子棋盘不是特殊棋盘,我们可以将其空闲方格位置(右上角)定义为特殊方格,让其变为一个特殊棋盘grid[tr + s][tc + s - 1] = t;chessBoard(tr + s, tc, tr + s, tc + s - 1, s);}// 如果特殊方格0位于右下角子棋盘中,则右下角子棋盘为特殊棋盘if (dr >= tr + s && dc >= tc + s) {// 分解特殊棋盘chessBoard(tr + s, tc + s, dr, dc, s);} else {// 否则,右下角子棋盘不是特殊棋盘,我们可以将其空闲方格位置(左上角)定义为特殊方格,让其变为一个特殊棋盘grid[tr + s][tc + s] = t;chessBoard(tr + s, tc + s, tr + s, tc + s, s);}}chessBoard(0, 0, row - 1, col - 1, size);return grid;
}/* 创建二维数组 */
function createGrid(row, col) {const grid = new Array(row);for (let i = 0; i < row; i++) {grid[i] = new Array(col);}return grid;
}

在写算法过程中,遇到的比较棘手的问题就是JavaScript创建二维数组。

我们不能使用 const 2dArr = new Array(8).fill(new Array(8))来创建二维数组,因为数组的fill方法会用入参填充数组元素。如果fill入参是一个对象,则被填充的数组的所有元素都指向该对象。

所以我们只能老老实实的for循环去创建。

另外 new Array(8)表示创建一个长度为8的数组,但是此时数组元素都是empty。

而当数组元素是empty时,数组原型上的一些方法,如forEach、map、filter、some、every、reduce将会跳过这些empty元素,所谓跳过,即这些empty元素不会进入callback回调。这是稀疏数组特性。

算法 - 棋盘覆盖(JavaScript)相关推荐

  1. 计算机基础算法棋盘覆盖,分治算法求解棋盘覆盖问题互动教学过程.doc

    分治算法求解棋盘覆盖问题互动教学过程 分治算法求解棋盘覆盖问题互动教学过程 摘要:针对算法设计与分析课程难度较大.对学生编程能力要求较高的现状,通过对棋盘覆盖问题的分治算法求解过程进行互动教学设计,引 ...

  2. 分治算法--棋盘覆盖

    问题描述 在一个2^k×2^k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘.在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特 ...

  3. 【算法】算法-棋盘覆盖

    demo 分治法: package ChessBoard;import java.util.Scanner;public class Main {public static void main(Str ...

  4. [算法][递归] 棋盘覆盖

    >_<: 问题描述: 在一个2k×2k 个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘.在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖 ...

  5. 算法设计棋盘覆盖问题c语言,棋盘覆盖问题(用分治法求解)

    // 棋盘覆盖 #include #include int Board[8][8]={0};//定义棋盘并初始化棋盘 void ChessBoard(int tr,int tc,int dr,int ...

  6. 算法设计与分析——递归与分治策略——棋盘覆盖

    问题描述 棋盘覆盖问题要求在2^k * 2^k 个方格组成的棋盘中,你给定任意一个特殊点,用一种方案实现对除该特殊点的棋盘实现全覆盖. 建立模型如图: 解决方案就是利用分治法,将方形棋盘分成4部分,如 ...

  7. 算法系列(一):分治策略--棋盘覆盖

    算法系列(一):分治策略--棋盘覆盖 一.分析 问题描述:  图1-1 k=2时的一个特殊棋盘 在一个 2^k * 2^k 个方格组成的棋盘中,若恰有一个方格与其它方格不同,则称该方格为一特殊方格,且 ...

  8. 算法篇-2-分治思想-棋盘覆盖归并排序Strasssen矩阵乘法循环赛安排

    本系列所有代码https://github.com/YIWANFENG/Algorithm-github 分治思想 分治法基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些问题互相独立且与 ...

  9. 浅谈棋盘覆盖问题(算法思想及伪代码)

    问题描述:在一个的方格组成的棋盘中,有一个方格与其他的方格不同,称之为奇异块.要求:若使用一下四种L型骨牌覆盖除这个奇异块的其他方格,覆盖过程中L型骨牌之间不能有互相覆盖,设计算法求出覆盖方案.(四种 ...

最新文章

  1. Flink在快手实时多维分析场景的应用
  2. 论文笔记之:End-to-End Localization and Ranking for Relative Attributes
  3. 南京大学计算机学院宋教授,宋曰钦教授
  4. leetcode 318. Maximum Product of Word Lengths | 318. 最大单词长度乘积
  5. mysql5.6与mysql5.5不同
  6. (篇六)C语言求自首数、完数、亲密数
  7. 2、网络编程之基于UDP示例
  8. ENVI学习总结(一)——自定义坐标系
  9. 基本技能 100256
  10. Java实现一个打飞机的小游戏【附源码】
  11. from functools import reduce——从典型实例做抓手看reduce函数使用
  12. 专访CAPA梁振宇:信息无障碍是互联网产品的必选项
  13. 【matlab】【Datcom】气动解算软件win10报错解决办法及运行交互示例
  14. 关于Android SD卡
  15. BGP/MPLS VS VPLS
  16. 心灵鸡汤:谦虚、不沉默、有危机感、不断努力
  17. 微信号:kcctvy 所谓的专业祛荨麻疹
  18. XP局域网共享设置图文教程
  19. 阿里CEO张勇解读入股高鑫零售:婚后怎么过日子已经谈得很好了
  20. MCDF验证学习笔记

热门文章

  1. MQTT的认识(1)
  2. 联想微型计算机怎么使用,lenovo电脑如何使用U盘引导教程(适用于一体机及台式机)...
  3. Scratch也能玩体感游戏
  4. 此远程计算机不支持remoteapp,部署RemoteApp实现应用程序的远程调用
  5. 解决Mysql报错:This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its de
  6. 伊隆马斯克提供了更多关于特斯拉骑乘网络的细节
  7. CentOS7使用yum安装Redis
  8. 【Nginx】Nginx原理与应用
  9. excel解决“输入值非法”问题
  10. Mysql之IGNORE关键字