分治法——棋盘覆盖问题/L形组件填图问题(Java实现)
问题描述
设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实现)相关推荐
- 分治法--棋盘覆盖问题
前几天学分治算法的时候碰到了一个经典的棋盘覆盖问题,现在小周周就来总结一下解题的过程吧,加强我们对分治算法的理解. 棋盘覆盖问题 问题描述:在一个2的K次方乘以2的K次方方格组成的棋盘中,一开始恰有一 ...
- java棋盘覆盖分治法,棋盘覆盖-分治法
信 息 工 程 学 院 算法分析 实习报告 学院:信息工程学院 班级:软件工程083 姓名: 学号: 成绩: 一.实习题目 : 棋盘覆盖 二.实习过程 : 1.了解分治法的思想: 将一个难以解决的大问 ...
- 算法设计与分析之分治法——棋盘覆盖
一:算法分析 棋盘覆盖问题要求在2^k * 2^k 个方格组成的棋盘中,你给定任意一个特殊点,用一种方案实现对除该特殊点的棋盘实现全覆盖. 建立模型如图:
- 分治法在求解“最近对”问题中的应用(JAVA)
分治法在求解"最近对"问题中的应用 最近对问题在蛮力法中有过讲解,时间复杂度为O(n^2),下面将会采用分治法讲解这类问题,时间复杂度会降到O(nlogn) 我们将笛卡尔平面上n& ...
- 计算机基础算法棋盘覆盖,分治算法求解棋盘覆盖问题互动教学过程.doc
分治算法求解棋盘覆盖问题互动教学过程 分治算法求解棋盘覆盖问题互动教学过程 摘要:针对算法设计与分析课程难度较大.对学生编程能力要求较高的现状,通过对棋盘覆盖问题的分治算法求解过程进行互动教学设计,引 ...
- 分治法:快速排序棋盘覆盖
目标 使用分治法解决快速排序问题 使用分治法解决棋盘覆盖问题 原理 一.快排原理 排序算法在工作中最常用,也是学习很多其他算法的前置知识,例如在运用二分查找算法之前,我们通常需要保证数据是有序的,如果 ...
- 棋盘覆盖-经典的分治法问题
棋盘覆盖-经典的分治法问题 一.问题概述 二.适用方法 三.代码展示 四.运行结果 五.算法分析 一.问题概述 在一个 2k×2k个方格组成的棋盘中,若恰有一个方格与其他方格不同,称该方格为特殊方格, ...
- 分治法解决棋盘覆盖问题
分治法解决棋盘覆盖问题 问题描述: 在一个2k×2k(k≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格.显然,特殊方格在棋盘中出现的位置有4k中情形,因而有4k中不同的棋盘. ...
- 【分治法】棋盘覆盖问题java实现
文章目录 问题描述 问题分析 算法设计 java代码 问题描述 在一个2k × 2k个放个中,恰好只有一个方格是残缺的.也就是在这个棋盘中有一个方格与其它的格子不同, 我们称这种棋盘为残缺棋盘. 下图 ...
最新文章
- 深度学习如何选择模型
- 互联网周刊:谁是下一个IE?
- 076_浏览器对象模型
- linux压缩和打包的区别,Linux中的压缩和打包
- php语言cookie,如何创建一个简单的PHP cookie语言切换?
- SQL点滴19—T-SQL中的透视和逆透视
- [bzoj3994] [SDOI2015]约数个数和
- CAP原理和最终一致性(Eventually Consistency)
- 小伙用C++搞定远程桌面监控系统,轻松拿下12家offer!
- 数字电路基础知识(一) 复位设计-同步复位与异步复位
- unity 导入STL格式模型(STL 文本ASCII码格式文件)
- 美团综合业务推荐系统的质量模型及实践
- autocad2007二维图画法_AutoCAD 2007矩形绘制方法教程
- 清华大学计算机通识选修,清华大学外语通识选修课调查分析-20210720010045.docx-原创力文档...
- L1-078吉老师的回归
- 如何使用UltraISO制作U盘系统盘用于重装系统
- 电脑的“应用与浏览器控制”出现黄色感叹号
- CountDownLatch--等待多线程计数器
- (附源码)spring boot学生社团管理系统的设计与实现 毕业设计 151109
- AJAX如何将参数带到并传给另一个页面?
热门文章
- Android开发工具系列 --Hosts映射
- Eth-Trunk(链路聚合)之负载分担模式
- 服务器并发处理是什么?
- python爬取网易云音乐飙升榜音乐_python爬取网易云音乐热歌榜实例代码
- 对话区块方舟Warren:DAO和隐私赛道被低估了 |链捕手
- 【数据结构】---堆排序+TOP-K问题(了解游戏排行底层原理)
- 安卓Android修改车机版系统的导航栏和状态栏高度
- 项目管理心得:一个项目经理的个人体会、经验总结
- 哈罗要在网约车市场取得突破,离开补贴行不通
- error: redefinition of ‘xxx’问题的解决