问题描述

设B是一个n×n棋盘,n=2k,(k=1,2,3,…)。用分治法设计一个算法,使得:用若干个L型条块可以覆盖住B的除一个特殊方格外的所有方格。其中,一个L型条块可以覆盖3个方格。且任意两个L型条块不能重叠覆盖棋盘。

例如:如果n=2,则存在4个方格,其中,除一个方格外,其余3个方格可被一L型条块覆盖;当n=4时,则存在16个方格,其中,除一个方格外,其余15个方格被5个L型条块覆盖。

具体要求

输入一个正整数n,表示棋盘的大小是n*n的。输出一个被L型条块覆盖的n*n棋盘。该棋盘除一个方格外,其余各方格都被L型条块覆盖住。为区别出各个方格是被哪个L型条块所覆盖,每个L型条块用不同的数字或颜色、标记表示。

测试数据

输入:8

输出:

解题思路

分治法

(一)什么是分治法

要想使用分治法解决此问题,我们就先需要了解一下什么是分治法。

分治法,简单来说,就是把一个问题不断地切分成与原问题性质相同、规模更小的子问题,直到子问题的规模足够小到可以直接求解,然后将子问题的解组合起来,得到原问题的解。

(二)分治法的一般解题步骤

由于分治法本身的递归特性,一般用递归实现分治算法。

分治法解题往往采用递归的方法实现,在递归求解子问题时同样要注意理清递归关系、递归出口、参数设置等问题。

最后,通过组合子问题形成原问题的解。

问题分析

面对L形组件填图问题,第一步我们需要思考如何划分

一个n * n的棋盘,我们可以想到有下面几种划分方式

我们可以看到,前两种划分会造成一个问题:划分后的子棋盘变成了长方形,而原问题是一个n * n的正方形,导致子问题性质和原问题性质不一样

所以,应采用第三种划分方式。

但这样子问题的性质就和原问题性质一样了吗?

注意,我们原问题所在的棋盘是有一个特殊方块(或者说是残缺方块),将原来的棋盘划分成四个子棋盘后,其中的一个子棋盘仍有特殊方块,但剩下的三个子棋盘没有特殊方块!

那如何使剩下的三个子棋盘都有特殊方块呢?

我们可以刚好依照问题要求,使用L形条块进行填充,作为该子棋盘的特殊方块,使得子问题与原问题性质相同

如此之后,我们就可以使用递归,求解问题

代码实现

棋盘表示

我们使用二维整型数组表示棋盘,使用数字(1、2、3....)进行填充,用0表示原问题的特殊方块(残缺方块)

区分四种棋盘

划分以后,我们会出现下面四种情况

如何区分四个子棋盘,以及如何区分特殊方块在哪一个子棋盘(左上、右上、左下、右下)中呢?

我们利用棋盘左上角的坐标和原棋盘大小(leftRow、leftCol、size)来标识一个棋盘

用specialRow、specialCol来表示特殊方块(残缺格)的位置

  • 如果特殊方块在左上的子棋盘中

即specialRow < leftRow + size/2 && specialCol < leftCol + size/2

第一步:递归该子棋盘

第二步:填充L型组件(即填充图中的蓝色方块)

第三步:递归其他三个子棋盘

  • 如果特殊方块在右上的子棋盘中

即specialRow < leftRow + size/2 && specialCol > leftCol + size/2

....(同上)

  • 如果特殊方块在左下的子棋盘中

即specialRow > leftRow + size/2 && specialCol < leftCol + size/2

...(同上)

  • 如果特殊方块在右下的子棋盘中

即specialRow > leftRow + size/2 && specialCol > leftCol + size/2

...(同上)

具体代码(java)

import java.util.Arrays;
import java.util.Scanner;public class Test1 {static int size;//棋盘大小static int[][] arr;//表示棋盘static int count = 1;//定义一个静态count用于填充public static void main(String[] args) {//1.接收参数nScanner sc = new Scanner(System.in);size = sc.nextInt();//2.创建n*n大小的二维数组arr = new int[size][size];//3.随机指定某一个位置为特殊方块(暂时假设第一行第一个元素为特殊方块)arr[0][0] = 0;Cover(0,0,0,0,size);Output(size);}//4.定义解决问题的函数public static void Cover(int leftRow,int leftCol,int specialRow,int specialCol,int size){//出口if(size < 2){return;}count++;int flag = count;//如果特殊方块在左上子棋盘if(specialRow < leftRow + size/2 && specialCol < leftCol + size/2){//递归覆盖该子棋盘Cover(leftRow,leftCol,specialRow,specialCol,size/2);//使得剩余的三个子棋盘性质与原问题相同arr[leftRow + size/2 - 1][leftCol + size/2] = flag;//填充右上子棋盘左下角arr[leftRow + size/2][leftCol + size/2 - 1] = flag;//填充左下子棋盘右上角arr[leftRow + size/2][leftCol + size/2] = flag;//填充右下棋盘左上角//递归覆盖三个子棋盘Cover(leftRow,leftCol+size/2,leftRow + size/2 - 1, leftCol + size/2,size/2);//右上子棋盘Cover(leftRow + size/2,leftCol,leftRow + size/2,leftCol + size/2 - 1,size/2);//左下子棋盘Cover(leftRow + size/2,leftCol + size/2,leftRow + size/2,leftCol + size/2,size/2);//右下子棋盘}else if(specialRow < leftRow + size/2 && specialCol >= leftCol + size/2){//如果特殊方块在右上子棋盘Cover(leftRow,leftCol + size/2,specialRow,specialCol,size/2);arr[leftRow + size/2 - 1][leftCol + size/2 - 1] = flag;//填充左上子棋盘右下角arr[leftRow + size/2][leftCol + size/2 - 1] = flag;//填充左下子棋盘右上角arr[leftRow + size/2][leftCol + size/2] = flag;//填充右下棋盘左上角Cover(leftRow,leftCol,leftRow + size/2 - 1, leftCol + size/2 - 1,size/2);//左上子棋盘Cover(leftRow + size/2,leftCol,leftRow + size/2,leftCol + size/2 - 1,size/2);//左下子棋盘Cover(leftRow + size/2,leftCol + size/2,leftRow + size/2,leftCol + size/2,size/2);//右下子棋盘}else if(specialRow >= leftRow + size/2 && specialCol < leftCol + size/2){//如果特殊方块在左下子棋盘Cover(leftRow + size/2,leftCol,specialRow,specialCol,size/2);arr[leftRow + size/2 - 1][leftCol + size/2 - 1] = flag;//填充左上子棋盘右下角arr[leftRow + size/2 - 1][leftCol + size/2] = flag;//填充右上子棋盘左下角arr[leftRow + size/2][leftCol + size/2] = flag;//填充右下棋盘左上角Cover(leftRow,leftCol,leftRow + size/2 - 1, leftCol + size/2 - 1,size/2);//左上子棋盘Cover(leftRow,leftCol+size/2,leftRow + size/2 - 1, leftCol + size/2,size/2);//右上子棋盘Cover(leftRow + size/2,leftCol + size/2,leftRow + size/2,leftCol + size/2,size/2);//右下子棋盘}else if(specialRow >= leftRow + size/2 && specialCol >= leftCol + size/2){//如果特殊方块在右下子棋盘Cover(leftRow + size/2,leftCol + size/2,specialRow,specialCol,size/2);arr[leftRow + size/2 - 1][leftCol + size/2 - 1] = flag;//填充左上子棋盘左下角arr[leftRow + size/2 - 1][leftCol + size/2] = flag;//填充右上子棋盘左下角arr[leftRow + size/2][leftCol + size/2 - 1] = flag;//填充左下子棋盘右上角Cover(leftRow,leftCol+size/2,leftRow + size/2 - 1, leftCol + size/2,size/2);//右上子棋盘Cover(leftRow + size/2,leftCol,leftRow + size/2,leftCol + size/2 - 1,size/2);//左下子棋盘Cover(leftRow + size/2,leftCol + size/2,leftRow + size/2,leftCol + size/2,size/2);//右下子棋盘}}public static void Output(int size){for (int i = 0; i < size; i++) {for (int j = 0; j < size; j++) {System.out.print(arr[i][j] + "\t");}System.out.println("");}}
}

运行结果

今天的内容就介绍到这啦,若对你有帮助的话就点个赞

分治法——棋盘覆盖问题/L形组件填图问题(Java实现)相关推荐

  1. 分治法--棋盘覆盖问题

    前几天学分治算法的时候碰到了一个经典的棋盘覆盖问题,现在小周周就来总结一下解题的过程吧,加强我们对分治算法的理解. 棋盘覆盖问题 问题描述:在一个2的K次方乘以2的K次方方格组成的棋盘中,一开始恰有一 ...

  2. java棋盘覆盖分治法,棋盘覆盖-分治法

    信 息 工 程 学 院 算法分析 实习报告 学院:信息工程学院 班级:软件工程083 姓名: 学号: 成绩: 一.实习题目 : 棋盘覆盖 二.实习过程 : 1.了解分治法的思想: 将一个难以解决的大问 ...

  3. 算法设计与分析之分治法——棋盘覆盖

    一:算法分析 棋盘覆盖问题要求在2^k * 2^k 个方格组成的棋盘中,你给定任意一个特殊点,用一种方案实现对除该特殊点的棋盘实现全覆盖. 建立模型如图:

  4. 分治法在求解“最近对”问题中的应用(JAVA)

    分治法在求解"最近对"问题中的应用 最近对问题在蛮力法中有过讲解,时间复杂度为O(n^2),下面将会采用分治法讲解这类问题,时间复杂度会降到O(nlogn) 我们将笛卡尔平面上n& ...

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

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

  6. 分治法:快速排序棋盘覆盖

    目标 使用分治法解决快速排序问题 使用分治法解决棋盘覆盖问题 原理 一.快排原理 排序算法在工作中最常用,也是学习很多其他算法的前置知识,例如在运用二分查找算法之前,我们通常需要保证数据是有序的,如果 ...

  7. 棋盘覆盖-经典的分治法问题

    棋盘覆盖-经典的分治法问题 一.问题概述 二.适用方法 三.代码展示 四.运行结果 五.算法分析 一.问题概述 在一个 2k×2k个方格组成的棋盘中,若恰有一个方格与其他方格不同,称该方格为特殊方格, ...

  8. 分治法解决棋盘覆盖问题

    分治法解决棋盘覆盖问题 问题描述: 在一个2k×2k(k≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格.显然,特殊方格在棋盘中出现的位置有4k中情形,因而有4k中不同的棋盘. ...

  9. 【分治法】棋盘覆盖问题java实现

    文章目录 问题描述 问题分析 算法设计 java代码 问题描述 在一个2k × 2k个放个中,恰好只有一个方格是残缺的.也就是在这个棋盘中有一个方格与其它的格子不同, 我们称这种棋盘为残缺棋盘. 下图 ...

最新文章

  1. 深度学习如何选择模型
  2. 互联网周刊:谁是下一个IE?
  3. 076_浏览器对象模型
  4. linux压缩和打包的区别,Linux中的压缩和打包
  5. php语言cookie,如何创建一个简单的PHP cookie语言切换?
  6. SQL点滴19—T-SQL中的透视和逆透视
  7. [bzoj3994] [SDOI2015]约数个数和
  8. CAP原理和最终一致性(Eventually Consistency)
  9. 小伙用C++搞定远程桌面监控系统,轻松拿下12家offer!
  10. 数字电路基础知识(一) 复位设计-同步复位与异步复位
  11. unity 导入STL格式模型(STL 文本ASCII码格式文件)
  12. 美团综合业务推荐系统的质量模型及实践
  13. autocad2007二维图画法_AutoCAD 2007矩形绘制方法教程
  14. 清华大学计算机通识选修,清华大学外语通识选修课调查分析-20210720010045.docx-原创力文档...
  15. L1-078吉老师的回归
  16. 如何使用UltraISO制作U盘系统盘用于重装系统
  17. 电脑的“应用与浏览器控制”出现黄色感叹号
  18. CountDownLatch--等待多线程计数器
  19. (附源码)spring boot学生社团管理系统的设计与实现 毕业设计 151109
  20. AJAX如何将参数带到并传给另一个页面?

热门文章

  1. Android开发工具系列 --Hosts映射
  2. Eth-Trunk(链路聚合)之负载分担模式
  3. 服务器并发处理是什么?
  4. python爬取网易云音乐飙升榜音乐_python爬取网易云音乐热歌榜实例代码
  5. 对话区块方舟Warren:DAO和隐私赛道被低估了 |链捕手
  6. 【数据结构】---堆排序+TOP-K问题(了解游戏排行底层原理)
  7. 安卓Android修改车机版系统的导航栏和状态栏高度
  8. 项目管理心得:一个项目经理的个人体会、经验总结
  9. 哈罗要在网约车市场取得突破,离开补贴行不通
  10. error: redefinition of ‘xxx’问题的解决