用分治法求解棋盘覆盖问题

合集下载

算法分析与设计教案

算法分析与设计教案

算法分析与设计课程教案课程编号:50c24037-01总学时:51 周学时:4适用年级专业(学科类):2007级计科专业开课时间:2010-2011 学年第1 学期使用教材:王晓东编著计算机算法设计与分析第3版章节第1章1.1~ 1.2 第2 章2.1 课时 2教学目的理解程序与算法的概念、区别与联系;掌握算法在最坏情况、最好情况和平均情况下的计算复杂性概念;掌握算法复杂性的渐近性态的数学表述;理解递归的概念。

教学重点及突出方法重点:程序与算法的概念、算法的时间复杂性、算法复杂性的渐近性态的数学表述以及递归的概念。

通过讲解、举例方法。

教学难点及突破方法难点:算法复杂性与递归通过讲解、举例、提问与引导方法。

相关内容此部分内容基础知识可参考清华大学出版社出版严蔚敏编著的《数据结构》教学过程(教师授课思路、设问及讲解要点)回顾数据结构课程中的算法概念、排序算法等知识,从而引出本课程内容。

提问算法与程序的区别、联系以及算法具有的特性。

讲解算法的复杂性,主要包括时间复杂性与空间复杂性。

讲解最坏情况、最好情况与平均情况的时间复杂性。

讲解算法复杂性在渐近意义下的阶,主要包括O、Ω、θ与o,并通过具体例子说明。

通过具体例子说明递归技术。

主要包括阶乘函数、Fibonacci数列、Ackerman函数、排列问题、整数划分问题、Hanoi塔问题等。

第页章节第2 章2.2~2.5 课时 2 教学目的掌握设计有效算法的分治策略,并掌握范例的设计技巧,掌握计算算法复杂性方法。

教学重点及突出方法重点:分治法的基本思想及分治法的一般设计模式。

通过讲解、举例方法。

教学难点及突破方法难点:计算算法复杂性。

通过讲解、举例、提问与引导方法。

相关内容素材教(教师授课思路、设问及讲解要点)学过程通过生活中解决复杂问题的分解方法,引出分治方法。

讲解分治法的基本思想及其一般算法的设计模式,介绍分治法的计算效率。

通过具体例子采用分治思想来设计有效算法。

如何应用分治算法求解问题

如何应用分治算法求解问题

如何应用分治算法求解问题分治算法,英文名为Divide and Conquer Algorithm,是一种高效的算法设计策略,在计算机科学中有着广泛的应用。

该算法将一个大问题分解成多个小问题,各自独立地解决,再将结果合并起来得到最终结果。

在本文中,我们将阐述如何应用分治算法求解问题,并通过几个实例来具体说明该算法的应用。

一、分治算法的原理分治算法的核心思想是将一个大问题分解成若干个小问题来解决,然后将这些小问题的解组合起来生成大问题的解。

其具体步骤如下:1. 分解:将原问题划分成若干个规模较小的子问题。

2. 解决:递归地解决每个子问题。

如果子问题足够小,则直接求解。

3. 合并:将所有子问题的解合并成原问题的解。

分治算法的主要优点在于它可以有效地缩小问题规模,从而缩短整个算法的执行时间。

另外,该算法天然适用于并行计算,因为每个子问题都是独立求解的。

二、分治算法的应用分治算法在各种领域都有广泛应用,包括数学、自然科学、计算机科学等。

以计算机科学领域为例,分治算法常常用于解决以下类型的问题:1. 排序问题2. 查找问题3. 字符串匹配问题4. 最大子序列和问题5. 矩阵乘法问题6. 图形问题下面我们将一一讲解这些问题的分治算法实现。

1. 排序问题排序问题是在一组数据中将其按指定规律进行排列的问题。

在计算机科学中,排序算法是十分重要的一类算法。

其中,分治算法由于其高效性和可并行性被广泛应用。

常用的分治排序算法包括归并排序和快速排序。

归并排序的基本思想是将待排序元素以中心点为界分成两个序列,对每个序列进行排序,然后将两个序列合并成一个有序序列;而快速排序则利用了分割的思想,通过每次选取一个元素作为“轴点”,将数组分成小于轴点和大于轴点的两部分,对这两部分分别进行快速排序。

2. 查找问题查找问题是在一组数据中寻找某个元素的问题。

分治算法在查找问题中的应用主要体现在二分查找中。

在二分查找中,我们首先将已排序的数组分成两半,在其中一半中查找目标值。

分治算法-残缺棋盘

分治算法-残缺棋盘

分治算法-残缺棋盘残缺棋盘是⼀个2^k*2^个⽅格的棋盘,其中恰有1个⽅格残缺。

图中给出,其中残缺部分⽤阴影表⽰。

这样的棋盘称为"三格板",残缺棋盘问题就是⽤这四种三格板覆盖更⼤的残缺棋盘。

再次覆盖中要求:(1)两个三格板不能重复。

(2)三格板不能覆盖残缺棋盘⽅格,但必须覆盖到其他所有的⽅格。

算法思路:利⽤分治算法将棋盘细化,逐步解决,以4*4为例⾸先判断残缺的位置在哪⾥,然后在中间填上对应的三格板,如在上图中间拼上三⾓板(4),变成下⾯这样然后通过中间将其分成了4个2*2的⼩残缺棋盘,从⽽问题得以解决4*4的分析过于简单,现在我们以8*8为例进⾏分析,能更清楚的理解这个例⼦中分治算法的思想⾸先将三格板放置在中间,将其分4个⼩的4*4的残缺棋盘通过红⾊线将其划分成4个4*4的残缺棋盘,现在以左上的残缺棋盘为例然后将左的4*4的⼩棋盘右划分成了4个2*2的⼩棋盘,这样就将问题优化成了2*2的三⾓棋盘的⼩问题,这样很快就能将左上的4*4的残缺棋盘解决了下⾯继续分析右上的4*4的棋盘,根据残缺的⽅格在⼩棋盘中的位置,在中间选择合适的三格板将⼩的残缺棋盘继续划分,将问题分化成更⼩的状态接着的问题和上⾯⼀样分析。

右上⾓的⼩棋盘很快也能解决了,下⾯两块残缺棋盘的分析⽅法和上⾯的⼀样,整个问题就这样⼀步步的分解成⼩问题,然后解决了。

下⾯是源代码#include <iostream>using namespace std;int amount,Board[100][100];void Cover(int tr,int tc,int dr,int dc,int size){int s,t;if(size<2)return ;amount++;t=amount;s=size/2;if(dr<tr+s&&dc<tc+s)//残缺在左上⾓{//覆盖中间位置Board[tr+s-1][tc+s]=t;Board[tr+s][tc+s-1]=t;Board[tr+s][tc+s]=t;Cover(tr,tc,dr,dc,s);//覆盖左上Cover(tr,tc+s,tr+s-1,tc+s,s);//覆盖右上Cover(tr+s,tc,tr+s,tc+s-1,s);//覆盖左下Cover(tr+s,tc+s,tr+s,tc+s,s);//覆盖右下}else if(dr<tr+s&&dc>=tc+s)//残缺在右上⾓{Board[tr+s-1][tc+s-1]=t;Board[tr+s][tc+s-1]=t;Board[tr+s][tc+s]=t;Cover(tr,tc,tr+s-1,tc+s-1,s);Cover(tr,tc+s,dr,dc,s);Cover(tr+s,tc,tr+s,tc+s-1,s);Cover(tr+s,tc+s,tr+s,tc+s,s);}else if(dr>=tr+s&&dc<tc+s)//残缺在左下 {Board[tr+s-1][tc+s-1]=t;Board[tr+s-1][tc+s]=t;Board[tr+s][tc+s]=t;Cover(tr,tc,tr+s-1,tc+s-1,s);Cover(tr,tc+s,tr+s-1,tc+s,s);Cover(tr+s,tc,dr,dc,s);Cover(tr+s,tc+s,tr+s,tc+s,s);}else{Board[tr+s-1][tc+s-1]=t;Board[tr+s-1][tc+s]=t;Board[tr+s][tc+s-1]=t;Cover(tr,tc,tr+s-1,tc+s-1,s);Cover(tr,tc+s,tr+s-1,tc+s,s);Cover(tr+s,tc,tr+s,tc+s-1,s);Cover(tr+s,tc+s,dr,dc,s);}}void Print(int s){for(int i=1;i<=s;i++){for(int j=1;j<=s;j++)printf("%5d ",Board[i][j]);printf("\n");}}int main(){int s=1,k,x,y;printf("输⼊2残缺棋盘的规模:2^k,k="); scanf("%d",&k);for(int i=1;i<=k;i++)s*=2;printf("输⼊棋盘残缺位置(x,y):");scanf("%d%d",&x,&y);Board[x][y]=0;Cover(1,1,x,y,s);Print(s);return 0;}。

算法设计与分析复习题目及答案 (3)

算法设计与分析复习题目及答案 (3)

分治法1、二分搜索算法是利用(分治策略)实现的算法。

9. 实现循环赛日程表利用的算法是(分治策略)27、Strassen矩阵乘法是利用(分治策略)实现的算法。

34.实现合并排序利用的算法是(分治策略)。

实现大整数的乘法是利用的算法(分治策略)。

17.实现棋盘覆盖算法利用的算法是(分治法)。

29、使用分治法求解不需要满足的条件是(子问题必须是一样的)。

不可以使用分治法求解的是(0/1背包问题)。

动态规划下列不是动态规划算法基本步骤的是(构造最优解)下列是动态规划算法基本要素的是(子问题重叠性质)。

下列算法中通常以自底向上的方式求解最优解的是(动态规划法)备忘录方法是那种算法的变形。

(动态规划法)最长公共子序列算法利用的算法是(动态规划法)。

矩阵连乘问题的算法可由(动态规划算法B)设计实现。

实现最大子段和利用的算法是(动态规划法)。

贪心算法能解决的问题:单源最短路径问题,最小花费生成树问题,背包问题,活动安排问题,不能解决的问题:N皇后问题,0/1背包问题是贪心算法的基本要素的是(贪心选择性质和最优子结构性质)。

回溯法回溯法解旅行售货员问题时的解空间树是(排列树)。

剪枝函数是回溯法中为避免无效搜索采取的策略回溯法的效率不依赖于下列哪些因素(确定解空间的时间)分支限界法最大效益优先是(分支界限法)的一搜索方式。

分支限界法解最大团问题时,活结点表的组织形式是(最大堆)。

分支限界法解旅行售货员问题时,活结点表的组织形式是(最小堆)优先队列式分支限界法选取扩展结点的原则是(结点的优先级)在对问题的解空间树进行搜索的方法中,一个活结点最多有一次机会成为活结点的是( 分支限界法).从活结点表中选择下一个扩展结点的不同方式将导致不同的分支限界法,以下除( 栈式分支限界法)之外都是最常见的方式.(1)队列式(FIFO)分支限界法:按照队列先进先出(FIFO)原则选取下一个节点为扩展节点。

(2)优先队列式分支限界法:按照优先队列中规定的优先级选取优先级最高的节点成为当前扩展节点。

用Java实现L型骨牌覆盖问题的分治算法分析

用Java实现L型骨牌覆盖问题的分治算法分析

象限
// 涂第 二象 限 i f ( dr <t r +s &&dc>=t c+s ){//特殊方块就在第二
Ch ess Boar d( t r ’t c+s ,d r ,dc,s) :
} el se {//第 二象限的 左下角 方块赋值 为t ( t i l e)
Boar d[ t r +s — 1] [ t c+s ] =t : // 涂第 二象 限其余 的方 块
( 下转第93页)
鼹■
应用 科学
关于x- ,x 2,xs的计算,程序中有具体的公式,而其它一些软约束条 件,也可通过各种方法得到实现,比如,要照顾岁数大的教师的问题,可 在数 据库 中排 序。 先排出 需要 照顾 的教师 的课 程, 然后 加一个 锁定 标记 , 这样 ,在 后边 的交 叉和变 异操 作中 ,这些 锁定 的点 也不 会被轻 易的 交换 , 保证了需要照 顾的特性。
2“×2卜l 2H×2“
2}l × 2缸l 2丘- l × 2丘_1

_■
l
图3 L型骨牌问题分治算法分析 设丁( 七) 为覆盖特殊棋盘的时间,当七=0时覆盖它需要常数时间 0( 1) .当 七>0时,测试 哪个子棋盘特殊 以及形成3个特殊子棋 盘需要 时『日J 0( 1) ,覆盖4个残缺子棋盘需四次递归调用,共需4 丁( 七一1) ,所以
一源代码privatevoichessboardintntdrntdcfsize1ntssize特殊方块就在第一象限chessboarcdrdcselse特殊方块不在第一象限第一象限的右下角方块赋值为t涂第一象限其余的方块chessboar特殊方块就在第二象限chessboarelse涂第二象限其余的方块chessboardtr特殊方块就在第三象限cilessb0ardt涂第三象限其余的方块chessb0ardt特殊方块就在第四象限chessb0ardtelsef第四象限的左上角方块赋值为t涂第四象限其余的方块chessboar下转第93页关于x2xs的计算程序中有具体的公式而其它一些软约束条件也可通过各种方法得到实现比如要照顾岁数大的教师的问题可在数据库中排序

计算机算法设计五大常用算法的分析及实例

计算机算法设计五大常用算法的分析及实例

计算机算法设计五⼤常⽤算法的分析及实例摘要算法(Algorithm)是指解题⽅案的准确⽽完整的描述,是⼀系列解决问题的清晰指令,算法代表着⽤系统的⽅法描述解决问题的策略机制。

也就是说,能够对⼀定规范的输⼊,在有限时间内获得所要求的输出。

如果⼀个算法有缺陷,或不适合于某个问题,执⾏这个算法将不会解决这个问题。

不同的算法可能⽤不同的时间、空间或效率来完成同样的任务。

其中最常见的五中基本算法是递归与分治法、动态规划、贪⼼算法、回溯法、分⽀限界法。

本⽂通过这种算法的分析以及实例的讲解,让读者对算法有更深刻的认识,同时对这五种算法有更清楚认识关键词:算法,递归与分治法、动态规划、贪⼼算法、回溯法、分⽀限界法AbstractAlgorithm is the description to the problem solving scheme ,a set of clear instructions to solve the problem and represents the describe the strategy to solve the problem using the method of system mechanism . That is to say, given some confirm import,the Algorithm will find result In a limited time。

If an algorithm is defective or is not suitable for a certain job, it is invalid to execute it. Different algorithms have different need of time or space, and it's efficiency are different.There are most common algorithms: the recursive and divide and conquer、dynamic programming method、greedy algorithm、backtracking、branch and bound method.According to analyze the five algorithms and explain examples, make readers know more about algorithm , and understand the five algorithms more deeply.Keywords: Algorithm, the recursive and divide and conquer, dynamic programming method, greedy algorithm、backtracking, branch and bound method⽬录1. 前⾔ (4)1.1 论⽂背景 (4)2. 算法详解 (5)2.1 算法与程序 (5)2.2 表达算法的抽象机制 (5)2.3 算法复杂性分析 (5)3.五中常⽤算法的详解及实例 (6)3.1 递归与分治策略 (6)3.1.1 递归与分治策略基本思想 (6)3.1.2 实例——棋盘覆盖 (7)3.2 动态规划 (8)3.2.1 动态规划基本思想 (8)3.2.2 动态规划算法的基本步骤 (9)3.2.3 实例——矩阵连乘 (9)3.3 贪⼼算法 (11)3.3.1 贪⼼算法基本思想 (11)3.3.2 贪⼼算法和动态规划的区别 (12)3.3.3 ⽤贪⼼算法解背包问题的基本步骤: (12)3.4 回溯发 (13)3.4.1 回溯法基本思想 (13)3.3.2 回溯发解题基本步骤 (13)3.3.3 实例——0-1背包问题 (14)3.5 分⽀限界法 (15)3.5.1 分⽀限界法思想 (15)3.5.2 实例——装载问题 (16)总结 (18)参考⽂献 (18)1. 前⾔1.1 论⽂背景算法(Algorithm)是指解题⽅案的准确⽽完整的描述,是⼀系列解决问题的清晰指令,算法代表着⽤系统的⽅法描述解决问题的策略机制。

棋盘覆盖问题算法思路

棋盘覆盖问题算法思路

棋盘覆盖问题算法思路
棋盘覆盖问题是一道经典的分治算法问题,通常用于介绍分治算法的思想。

其基本思路是将棋盘分成若干个小块,然后在其中一个小块上放置一块特殊的骨牌,然后将剩下的小块按照同样的方式继续分成更小的块,并在其中一个小块上放置另一块骨牌,以此类推,直到整个棋盘被覆盖。

具体的实现过程可以采用递归的方式,将棋盘不断地分成四个部分,然后在其中一个部分上放置一块骨牌,再递归求解另外三个部分。

在实现过程中,需要注意处理边界条件和特殊情况,例如棋盘大小为1x1或者存在特殊方块无法覆盖等情况。

该算法的时间复杂度为O(2^n),其中n为棋盘大小的指数。

虽然时间复杂度较高,但是由于该问题特殊的递归性质使得其能够被高效地并行化,因此在实际应用中仍有广泛的应用。

最小权顶点覆盖问题分支界限法

最小权顶点覆盖问题分支界限法

最小权顶点覆盖问题分支界限法最小权顶点覆盖问题是一个经典的组合优化问题。

该问题可以描述为:给定一个无向图G=(V,E),图中每个顶点v都有一个权值w(v),要求找到最小的顶点集合C,使得对于图中的每条边(u,v),至少有一个顶点在C中。

同时,要求C中所有顶点的权值之和最小。

分支界限法是一种解决组合优化问题的算法。

它通过将问题划分为若干个子问题,并对每个子问题进行求解和限界,从而逐步找到最优解。

下面是使用分支界限法求解最小权顶点覆盖问题的详细步骤:1. 定义问题的数学模型。

将最小权顶点覆盖问题表示为一个整数线性规划问题,目标函数为最小化C中顶点的权值之和,约束条件为每条边至少有一个顶点在C中。

2. 构造初始解。

初始化一个空的顶点集合C,将问题表示为一个根节点。

3. 基于当前解构造子问题。

从图中选择一个未被覆盖的顶点v,将其加入C中。

将问题分为两个子问题:子问题1是从图中删除顶点v及其相关的边,子问题2是从图中删除顶点v的邻居及其相关的边。

4. 求解子问题。

对两个子问题分别应用分支界限法进行求解。

对子问题1,建立新的根节点,并更新C;对子问题2,将v加入C,并更新问题。

5. 更新最优解。

每当找到一个新的最优解时,更新最优解的权值之和,并记录下来。

同时,记录下来所有已解的子问题。

6. 剪枝操作。

根据已解的子问题和最优解进行剪枝操作,减少搜索空间。

7. 重复步骤3-6,直到找到最优解或搜索空间为空。

在进行分支界限法求解最小权顶点覆盖问题时,可以采用以下的优化策略:1. 首先根据顶点的权值进行排序,优先选择权值较小的顶点进行划分。

这样可以在尽可能少地搜索空间的情况下找到最优解。

2. 使用线性规划松弛技术对每个子问题进行限界。

通过找到整数线性规划问题的线性松弛下界,可以快速排除那些不可能成为最优解的子问题。

3. 使用启发式算法进行问题求解。

通过结合启发式算法和分支界限法,可以在搜索空间较大时快速找到较优解。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

棋盘覆盖问题
问题描述:
在一个2k ×2k (k ≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。

显然,特殊方格在棋盘中出现的位置有4k 中情形,因而有4k 中不同的棋盘,图(a )所示是k=2时16种棋盘中的一个。

棋盘覆盖问题要求用图(b )所示的4中不同形状的L 型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且热河亮哥L 型骨牌不得重复覆盖。

问题分析:
K>0时,可将2k ×2k 的棋盘划分为4个2k-1×2k-1的子棋盘。

这样划分后,由于原棋盘只有一个特殊方格,所以,这4个子棋盘中只有1个子棋盘中有特殊方格,其余3个子棋盘中没有特殊方格。

为了将这3个没有特殊方格的子棋盘转化成为特殊棋盘,以便采用递归方法求解,可以用一个L 型骨牌覆盖这3个较小的棋盘的会合处,从而将原问题转化为4个较小规模的棋盘覆盖问题。

递归地使用这种划分策略,直至将棋盘分割为1×1的子棋盘。

问题求解:
下面介绍棋盘覆盖问题中数据结构的设计。

(1) 棋盘:可以用一个二维数组board[size][size]表示一个棋盘,其中size=2k 。

为了
在递归处理的过程中使用同一个棋盘,将数组board 设为全局变量。

(2) 子棋盘:整个棋盘用二维数组board[size][size]表示,其中的子棋盘由棋盘左上
角的下标tr 、tc 和棋盘大小s 表示。

(3) 特殊方格:用board[dr][dc]表示特殊方格,dr 和dc 是该特殊方格在二维数组
board 中的下标。

(4) L 型骨牌:一个2k ×2k 的棋盘中有一个特殊方格,所以,用到L 型骨牌的个数
为(4k -1)/3,将所有L 型骨牌从1开始连续编号,用一个全局变量tile 表示。

图(b ) 图 (a )
C语言源码:
/*author: 彭洪伟
*studentID:0950310006
*class:计科1班
*problem:分治法解决棋盘覆盖问题
*/
#include <stdio.h>
#include <math.h>
int tile=1; //记录骨牌的型号
int board[20][20]={0}; //存储棋盘被覆盖的情况
void ChessBoard(int tr,int tc,int dr,int dc,int size)
{ //tr和tc是棋盘左上角的下标,dr和dc是特殊方格的下标,size是棋盘的大小int t=0;
int s;
if (size==1)return;
t=tile++;
s=size/2; //划分棋盘
//覆盖左上角棋盘
if (dr<tr+s&&dc<tc+s) //特殊方格在棋盘的左上角
ChessBoard(tr,tc,dr,dc,s);
else
{
board[tr+s-1][tc+s-1]=t;
ChessBoard(tr,tc,tr+s-1,tc+s-1,s);
}
//覆盖右上角棋盘
if (dr<tr+s&&dc>=tc+s) //特殊方格在棋盘的右上角
ChessBoard(tr,tc+s,dr,dc,s);
else
{
board[tr+s-1][tc+s]=t;
ChessBoard(tr,tc+s,tr+s-1,tc+s,s);
}
//覆盖左下角棋盘
if (dr>=tr+s&&dc<tc+s) //特殊方格在棋盘的左下角
ChessBoard(tr+s,tc,dr,dc,s);
else
{
board[tr+s][tc+s-1]=t;
ChessBoard(tr+s,tc,tr+s,tc+s-1,s);
}
//覆盖右下角棋盘
if (dr>=tr+s&&dc>=tc+s) //特殊方格在棋盘的右下角ChessBoard(tr+s,tc+s,dr,dc,s);
else
{
board[tr+s][tc+s]=t;
ChessBoard(tr+s,tc+s,tr+s,tc+s,s);
}
}
int main()
{
int k,x,y;
printf("请输入棋盘的规模K:");
scanf("%d",&k);
printf("请输入特殊方格的下标x,y:");
scanf("%d %d",&x,&y);
ChessBoard(0,0,x,y,pow(2,k));
for(int i=0; i<pow(2,k); i++)
{
for (int j=0; j<pow(2,k); j++)
{
printf("%-4d",board[i][j]);
}
printf("\n");
}
return 0;
}
运行结果截图:。

相关文档
最新文档