棋盘覆盖问题(Java)

简介: 棋盘覆盖问题(Java)

棋盘覆盖问题(Java)


a53fa7633514475fa766316fab7a2e3e.jpeg



1、问题描述

  在一个2k×2k个方格组成的棋盘中,若恰有一个方格与其他方格不同,则称该方格为一特殊方格,且称该棋盘为一个特殊棋盘。显然特殊方格在棋盘上出现的位置有4k 种情形.因而对任何 k ≥ 0 ,有4k种不同的特殊棋盘。如下图中的特殊棋盘是当 k = 2 时16个特殊棋盘中的一个。

1.png

 

在棋盘覆盖问题中,要用下图所示的4种不同形态的 L型 骨牌覆盖一个给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。易知,在任何一个2k×2k的棋盘覆盖中,用到的L型骨牌个数恰好为(4k - 1)/3。


2.jpeg


2、算法设计思路

使用分治策略,可以设计出解棋盘覆盖问题的简洁算法。



k>0 时,将2k×2k棋盘分割为4个2k-1×2k-1 子棋盘,如下图(a)所示。


特殊方格必位于4个 较小子棋盘之一 中,其余3个子棋盘中无特殊方格。为了将这3个无特殊方格的子棋盘转化为特殊棋盘,可以用一个L型骨牌覆盖这3个较小棋盘的 会合处 ,如下图(b)所示,从而将原问题转化为4个较小规模的棋盘覆盖问题。 递归 地使用这种分割,直至棋盘简化为棋盘 1×1

3e.png


3、代码实现


特殊棋盘我们采用0来表示,同时假设特殊方格的位置为第三行第三列


棋盘一分为四之后,依次覆盖左上角子棋盘、右上角子棋盘、左下角子棋盘、右下角子棋盘。如若特殊方格在子棋盘中,则递归执行该子棋盘的操作;若不在,对于左上角子棋盘、右上角子棋盘、左下角子棋盘、右下角子棋盘而言,用编号为t的L型骨牌依次覆盖右下角、左下角、右上角、左上角的方格。


/

4.jpeg

/*** TODO  棋盘覆盖算法 特殊棋盘我们采用0来表示**/publicclasschessBoard {
staticfinalintSIZE=4;
staticint[][] board=newint[SIZE][SIZE];
staticinttitle=1; // title表示L型骨牌的编号publicstaticvoidmain(String[] args) {
// TODO 假设特殊方格的位置为第三行第三列board[2][2] =0;
ChessBoard(0, 0, 2, 2, SIZE);
System.out.println(SIZE+"*"+SIZE+"的L型骨牌棋盘为:");
for (inti=0; i<SIZE; ++i) {
for (intj=0; j<SIZE; j++) {
System.out.print(board[i][j] +"  ");
            }
System.out.println();
        }
    }
/**** @param tr    表示棋盘左上角行号* @param tc    表示棋盘左上角列号* @param dr    表示特殊棋盘的行号* @param dc    表示特殊棋盘的列号* @param size  =2^k。棋盘的规格为2^k*2^k*/publicstaticvoidChessBoard(inttr, inttc, intdr, intdc, intsize) {
if (size==1) {
return;
        }
intt=title++;    // t表示L型骨牌的编号ints=size/2;   // 分割的子棋盘的规格大小(切分为4个子棋盘)// TODO 1.覆盖左上角子棋盘if (dr<tr+s&&dc<tc+s) {
// TODO 说明特殊方格在此子棋盘中ChessBoard(tr, tc, dr, dc, s);
        } else {
// TODO 说明特殊方格不在此子棋盘中//  用t号L型棋盘覆盖这个子棋盘的右下角board[tr+s-1][tc+s-1] =t;
// TODO 覆盖其余棋盘方格ChessBoard(tr, tc, tr+s-1, tc+s-1, s);
        }
// TODO 2.覆盖右上角子棋盘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);
        }
// TODO 3.覆盖左下角子棋盘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);
        }
// TODO 4.覆盖右下角子棋盘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);
        }
    }
}



4、复杂度分析


设T(k)是算法chessBoard覆盖一个2k×2k棋盘所需的时间。从算法的分隔策略可以知道,T(k)满足以下的递归方程:


  • 当k = 0时,T(k) = O(1),
  • 当k > 0时,T(k) = 4T(k - 1) + O(1)


最终此递归方程可得:T(n) = O(4k)。

由于覆盖2k×2k棋盘所需的L型骨牌个数为(4k - 1)/3,所以此算法是一个在渐进意义下的最优算法。

5.jpeg


5、参考

  • 算法分析与设计(第四版)


目录
相关文章
|
定位技术 API 开发者
地图:nuxt3高德地图简单使用
地图:nuxt3高德地图简单使用
674 0
|
8月前
|
消息中间件 人工智能 Serverless
主动式智能导购AI助手构建解决方案评测
主动式智能导购AI助手构建解决方案评测
362 3
|
机器学习/深度学习 PyTorch 算法框架/工具
神经网络中的分位数回归和分位数损失
在使用机器学习构建预测模型时,我们不只是想知道“预测值(点预测)”,而是想知道“预测值落在某个范围内的可能性有多大(区间预测)”。例如当需要进行需求预测时,如果只储备最可能的需求预测量,那么缺货的概率非常的大。但是如果库存处于预测的第95个百分位数(需求有95%的可能性小于或等于该值),那么缺货数量会减少到大约20分之1。
812 2
|
11月前
|
运维 Linux 开发工具
第22篇 如何部署gitLab进行开发版本控制
第22篇 如何部署gitLab进行开发版本控制
|
Linux Docker 容器
docker 国内镜像源
【8月更文挑战第26天】
3698 1
|
PyTorch TensorFlow API
Transformers 4.37 中文文档(八十四)(4)
Transformers 4.37 中文文档(八十四)
304 4
|
消息中间件 Linux
Centos安装RabbitMQ
Centos安装RabbitMQ
158 3
|
数据安全/隐私保护
硬盘坏道如何检测和修复?
本文介绍了硬盘坏道的概念,包括逻辑坏道和物理坏道的区别,并提供了使用DiskGenius检测和修复坏道的步骤。当硬盘出现坏道且包含重要数据时,应立即备份数据,使用数据恢复软件,或在严重情况下寻求专业帮助。保护和恢复数据是应对硬盘坏道的关键。
|
数据可视化 数据挖掘 索引
【数据分析与可视化】时间序列中日期范围、频率、移位、时期的讲解(图文解释 超详细)
【数据分析与可视化】时间序列中日期范围、频率、移位、时期的讲解(图文解释 超详细)
264 0
|
机器学习/深度学习 自然语言处理 算法
深度学习算法简介(一)
深度学习算法简介(一)
427 0