棋盘覆盖问题 分治法c(带截图)
分治算法-残缺棋盘
分治算法-残缺棋盘残缺棋盘是⼀个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;}。
算法设计与分析课件--分治法-线性时间选择
2.5 线性时间选择
这样找到的m*划分是否能达到O(n)的时间复杂度? |A| = |D| = 2r, |B| = |C| = 3r +2,n = 10r +5. |A| + |D| + |C| = 7r + 2 = 7(n-5)/10 +2 = 7n/10 -1.5 < 7n/10 表明子问题的规模不超过原问题的7/10(d)。
T(n) = T(cn) + T(dn) + tn
6
2.5 线性时间选择
Select(S, k) Input: n个数的数组S,正整数k
T(n) = T(cn) + T(dn) + tn
Output: S中的第k个小元素
1. 将S划分成5个元素一组,共[n/5]个组;
2. 每组寻找一个中位数,把这些中位数放到集合M中;
寻找一个分割点m*, 使得左边子表S1中的元素都小于m*, 右子表 S2中的元素都大于m*。 如果寻找m*的时间复杂度达到O(nlogn), 那就不如直接使用排序 算法了。 如果直接寻找m*, 时间复杂度是O(n). 假设选择算法的时间复杂度为T(n), 递归调用这个算法在S的一 个真子集M上寻找m*,应该使用T(cn)时间,这里c是小于1的常数, 反映了M的规模与S相比缩小许多。
✓ 不妨假设n是5的倍数,且n/5是奇数,即n/5 = 2r+1. 于是: |A| = |D| = 2r, |B| = |C| = 3r +2,n = 10r +5.
✓ 如果A和D中的元素都小于m*,那么把它们的元素都加入到S1, S1对应规约后子问题的上限。 类似的,若A和D中的元素都 大于m*, 则把他们的元素都加 入到S2,S2对应规约后子问题 的上限。
算法设计与分析复习题目及答案 (3)
分治法1、二分搜索算法是利用(分治策略)实现的算法。
9. 实现循环赛日程表利用的算法是(分治策略)27、Strassen矩阵乘法是利用(分治策略)实现的算法。
34.实现合并排序利用的算法是(分治策略)。
实现大整数的乘法是利用的算法(分治策略)。
17.实现棋盘覆盖算法利用的算法是(分治法)。
29、使用分治法求解不需要满足的条件是(子问题必须是一样的)。
不可以使用分治法求解的是(0/1背包问题)。
动态规划下列不是动态规划算法基本步骤的是(构造最优解)下列是动态规划算法基本要素的是(子问题重叠性质)。
下列算法中通常以自底向上的方式求解最优解的是(动态规划法)备忘录方法是那种算法的变形。
(动态规划法)最长公共子序列算法利用的算法是(动态规划法)。
矩阵连乘问题的算法可由(动态规划算法B)设计实现。
实现最大子段和利用的算法是(动态规划法)。
贪心算法能解决的问题:单源最短路径问题,最小花费生成树问题,背包问题,活动安排问题,不能解决的问题:N皇后问题,0/1背包问题是贪心算法的基本要素的是(贪心选择性质和最优子结构性质)。
回溯法回溯法解旅行售货员问题时的解空间树是(排列树)。
剪枝函数是回溯法中为避免无效搜索采取的策略回溯法的效率不依赖于下列哪些因素(确定解空间的时间)分支限界法最大效益优先是(分支界限法)的一搜索方式。
分支限界法解最大团问题时,活结点表的组织形式是(最大堆)。
分支限界法解旅行售货员问题时,活结点表的组织形式是(最小堆)优先队列式分支限界法选取扩展结点的原则是(结点的优先级)在对问题的解空间树进行搜索的方法中,一个活结点最多有一次机会成为活结点的是( 分支限界法).从活结点表中选择下一个扩展结点的不同方式将导致不同的分支限界法,以下除( 栈式分支限界法)之外都是最常见的方式.(1)队列式(FIFO)分支限界法:按照队列先进先出(FIFO)原则选取下一个节点为扩展节点。
(2)优先队列式分支限界法:按照优先队列中规定的优先级选取优先级最高的节点成为当前扩展节点。
算法设计与分析-分治法
3.2.1 归并排序
算法3.1——归并排序
void MergeSort(int r[ ], int r1[ ], int s, int t) {
if (s= =t) r1[s]=r[s]; //只有一个元素,直接赋值 else {
m=(s+t)/2; Mergesort(r, r1, s, m); //归并排序前半个子序列 Mergesort(r, r1, m+1, t); //归并排序后半个子序列 Merge(r1, r, s, m, t); //合并两个已排序的子序列 } }
A、B、C、D 四个区域
Ø想法
Ø 用二维数组data[N][N]表示N×N的方阵,观察方阵中数
字的规律,可以从外层向里层填数。 Ø 设变量size表示方阵的大小,则初始时size = N,填完一
层则size = size - 2;
Ø想法
Ø 设变量begin表示每一层的起始位置,变量i和j分别表示
MergeSort(r,r1,1,1) r1[1]=r[1]
Merge(r1,r,0,0,1)
MergeSort(r,r1,2,3)
MergeSort(r,r1,2,2) r1[2]=r[2]
MergeSort(r,r1,3,3) r1[3]=r[3]
Merge(r1,r,2,2,3)
Merge(r1,r,0,1,3)
• 分治思想 • 归并排序 • 快速排序 • 折半查找 • 选择问题 • 最大子段和问题 • 棋盘覆盖问题 • 循环赛日程安排问题
3.1 基本思想 3.2 排序问题中的分治算法 3.3 查找问题中的分治算法 3.4 组合问题中的分治算法 3.5 典型问题的C++程序(略)
棋盘覆盖问题c语言
// 覆盖本子棋盘中的其余方格
ChessBoard(tr,tc,tr+s-1,tc+s-1,s);
}
//覆盖右上角子棋盘
if(dr<tr+s&&dc>=tc+s)
// 特殊方格在此棋盘中
ChessBoard(tr,tc,dr,dc,s);
else
{//特此棋盘中无特殊方格 ,t号L型骨牌覆盖左下角
{//此棋盘中无特殊方格 ,t号L型骨牌覆盖左上角
board[tr+s][tc+s]=t;
// 覆盖本子棋盘中的其余方格
ChessBoard(tr+s,tc+s,tr+s,tc+s,s);
}
}
int main()
{
int size,r,c,row,col;
printf("输入棋盘大小:\n");
scanf("%d",&size);//输入棋盘大小
{
for (c = 0; c < size; c++)
{
printf("%d ",board[r][c]);
}
printf("\n");
}
return 0;
}
运行效果:
实验报告成绩
老师
注:1)专业班级按打印课表中名称填写;2)课程名称按课表中名称填写,不能简写;
3)实验日期格式示例:)实验时间格式示例:“第三大节”5)实验情况包括任务(或题目)、解决方案(或者代码)、结果等;6)实验报告成绩按五级标准评分;精心搜集整理,只为你的需要
棋盘式算法
棋盘式算法(checkerboard algorithm)是一种并行计算算法,常用于解决二维网格上的计算问题。
该算法将计算任务分配到不同的处理器上,每个处理器负责计算一个子区域,最后将结果合并得到最终结果。
具体来说,棋盘式算法的流程如下:
1.将二维网格分成若干个大小相同的子块,每个子块包含连续的行和列。
2.将子块按照黑白相间的方式分配给处理器,即交替分配黑块和白块给不同的处理器。
3.处理器对自己分配到的子块进行计算,得到局部结果。
4.处理器之间进行通信,将边界处的结果传递给相邻的处理器。
5.处理器根据收到的结果更新自己的计算结果。
6.重复步骤3-5,直到所有处理器都完成了计算。
7.合并所有处理器的计算结果,得到最终结果。
棋盘式算法的优点在于可以充分利用多处理器系统的并行计算能力,同时减少了处理器之间的通信量,提高了运算效率。
这种算法常用于解决图像处理、模拟物理效应等需要大量计算的问题,具有广泛的应用前景。
棋盘理论知识点总结
棋盘理论知识点总结棋盘理论是图论的一个重要领域,研究的对象是在一个给定的网格状的结构上,如棋盘等,给定一些特定的规则和限制条件下的一些问题的性质和解法。
棋盘理论在数学、计算机科学、经济学、生物学等领域有着广泛的应用,例如在游戏算法、路径规划、资源分配等方面。
本文将从基本概念、经典问题、相关算法等方面对棋盘理论进行总结和介绍。
一、基本概念1.1 图论基础棋盘理论是图论的一个分支,图论是数学的一个分支,研究的对象是图。
图由结点(vertex)和边(edge)组成,其中结点代表实体,边代表结点之间的关系。
在棋盘理论中,棋盘可以看作一个特殊的图,其中每个格点都是一个结点,相邻的格点用边连接。
通过图论的概念和方法,可以更好地理解和分析棋盘理论中的问题。
1.2 状态空间在棋盘理论中,状态空间是指所有可能的状态的集合。
每个状态对应着棋盘上的一个局面,可以是游戏中的某个局面,也可以是路径规划中的某个位置等。
在状态空间中,通常会定义一些操作,使得在不同状态之间能够进行状态转移。
状态空间的性质和结构对于理解问题和设计算法有着重要的作用。
1.3 博弈论基础博弈论是研究多方参与的竞争行为的数学理论。
在棋盘理论中,经常会涉及到博弈论的相关概念和方法。
例如,博弈树、极小-极大搜索等算法都是博弈论在棋盘理论中的应用。
通过博弈论的分析,可以找到一些最优的策略和决策,对于解决棋盘理论中的一些问题非常重要。
1.4 相关算法在棋盘理论中,会涉及到一些经典的算法,例如深度优先搜索(DFS)、广度优先搜索(BFS)、最短路径算法、最小生成树算法等。
这些算法在解决棋盘理论中的一些问题时,起着非常重要的作用。
通过这些算法,可以有效地求解一些复杂的问题,提高求解的效率和质量。
二、经典问题2.1 马踏棋盘问题马踏棋盘问题是棋盘理论中的一个经典问题,也是图论中的一个经典问题。
问题描述如下:在一个给定大小的棋盘上,有一个马,它从任意一个位置开始,按照马的走法进行移动,要求每个格点只能访问一次,最终能否遍历整个棋盘上的所有格点。
分治法棋盘覆盖问题算法原理
分治法棋盘覆盖问题算法原理
分治法棋盘覆盖问题算法是一种基于分治策略的算法,用于解决棋盘覆盖问题。
该算法的基本原理是将一个复杂的问题分解为若干个较小的子问题,然后分别求解这些子问题,最后将子问题的解合并为原问题的解。
在棋盘覆盖问题中,给定一个n×n的棋盘,要求用最少的1×2骨牌覆盖整个棋盘。
分治法棋盘覆盖问题算法通过将棋盘不断划分,将问题规模逐渐减小,最终将问题转化为若干个1×1的棋盘覆盖问题,从而使得问题得以解决。
具体来说,该算法首先将棋盘划分为四个相等的子棋盘,然后判断哪个子棋盘中包含特殊方格。
对于不包含特殊方格的子棋盘,用L型骨牌覆盖其会合处,将其转化为特殊棋盘。
然后递归地使用这种划分策略,直至将棋盘分割为1×1的子棋盘。
通过这种分治策略,算法可以将问题规模不断减小,直到每个子问题都能够被直接解决。
最终,所有子问题的解将被合并为原问题的解。
这种算法不仅具有高效性,而且能够将复杂的问题分解为若干个简单的子问题,使得问题的解决更加容易。
棋盘上的数学问题
希望杯
希望杯
学数
数学
竞 赛 题 竞 赛 题
(a)
(b)
图4
(要求 :每次移动网格中的字块时 ,只能
将字块滑动到相邻的空的网格中. )
(第 16 届“希望杯”全国数学邀请赛)
解 :将“希 、望 、杯 、数 、学 、竞 、赛 、题”八个
字分别记为 1 、2 、3 、4 、5 、6 、7 、8 ,则图 4 (a) 变为
③
a4 + a5 + a6 = 15.
④
①+ ②+ ③+ ④得
3 a5 + ( a1 + a2 + …+ a9 ) = 60 ,
即 3 a5 + 45 = 60 ,得 a5 = 5.
余下的 8 个数中有 4 个偶数 、4 个奇数.
若假设 a1 为奇数 ,则由式 ①知 a9 必为奇数.
分类讨论如下 :
14
综上 ,如图 8 所填的 3 ×3 棋盘 , 使 M 有最大 值 ,且最大值为 58.
注 :填数方法不唯一.
4 棋盘的覆盖问题
817 492 536
图8
这 里 的 覆 盖 问 题 是 指 最 简 单 的 一 类 覆
盖 ,即棋盘的完全覆盖 (在棋盘的覆盖中 ,各
个覆盖形的总格数等于棋盘的总格数) . 完全
在 3 ×3 网格的同一行中 ,按照要求调整 时 ,对应数字只能左右移动 ,移动前后的棋盘 所对应的八位数完全相同 ,相应的逆序的总 数不发生变化.
如果按照要求 ,将数字移动到相邻的行 中 ,相当于在对应的八位数中 ,将某个数字向 左 (或向右) 跳过了两个数字. 注意到在一个 多位数中 ,两个相邻数字交换位置 ,逆序总数 的变化量只能是 1 或 - 1 ,于是 ,将数字移动 到相邻的行时 ,对应的八位数的逆序总数的 变化量只能是 2 或 0 或 - 2.
棋盘覆盖算法
棋盘覆盖算法
棋盘覆盖算法是一种使用分治策略来覆盖一个给定的棋盘的算法。
其基本思想是将棋盘划分成四个等分的子棋盘,然后从中选择一个作为特殊方格,并在其它三个子棋盘上递归执行该算法。
这个过程会一直递归下去,直到棋盘被完全覆盖。
在实际应用中,棋盘覆盖算法可以用来解决一些与棋盘相关的问题,例如:在一个棋盘上,如何用L型骨牌覆盖所有格子?如何在一个棋盘上放置n个皇后,使得它们不互相攻击?
棋盘覆盖算法的时间复杂度为O(2^n),因此在处理大规模的棋盘问题时,可能会存在效率问题。
为了提高算法的效率,可以考虑使用一些优化技巧,例如:使用启发式搜索来减少搜索空间,或者使用记忆化搜索来避免重复计算。
总之,棋盘覆盖算法是一种十分有用的算法,在许多棋盘相关的问题中都能够得到应用。
- 1 -。
棋盘覆盖(分治法)
}
/*left,top:方块的左上角坐标,x,y:特殊方块的坐标 size:当前的子棋盘大小*/
void ChessBoard(int left,int top,int x,int y,int size)
{
int i,t,s,pos;/*t是方块的编号,s是棋盘的一半尺寸!(size/2),pos表示方块位于哪一角 */
scanf("%d",&y);
if(k<0 || k>6 || x<0 || x>(size-1) || y<0 || y>(size-1))
{
printf("Input invalid!\n");
return;
}
InitGraph();
{
for(i=0;i<size;i++)
{
printf("%2d ",Board[i][j]);
}
printf("\n");
}
printf("\n--------------------------------\n");
{
setfillstyle(SOLID_FILL,color);
rectangle(BoardLeft+x*CellSize,BoardTop+y*CellSize,BoardLeft+(x+1)*CellSize,BoardTop+(y+1)*CellSize);
floodfill(BoardLeft+x*CellSize+CellSize/2,BoardTop+y*CellSize+CellSize/2,BorderColor);
【算法复习二】传统基本算法(分治----残缺棋盘问题)
【算法复习⼆】传统基本算法(分治----残缺棋盘问题)• 问题描述:残缺棋盘是⼀个有2k×2k (k≥1)个⽅格的棋盘,其中恰有⼀个⽅格残缺。
如图给出k=1时各种可能的残缺棋盘,其中残缺的⽅格⽤阴影表⽰。
• 残缺棋盘问题就是要⽤这四种三格板覆盖更⼤的残缺棋盘。
在此覆盖中要求:1)两个三格板不能重叠2)三格板不能覆盖残缺⽅格,但必须覆盖其他所有的⽅格。
⼩格⼦数(2k×2k -1)三格板中⼩格⼦数3。
所以所需要的三格板总数为(2k×2k -1 )/3。
• 例如,⼀个4*4的残缺棋盘2k*2k以k=2时的问题为例,⽤⼆分法进⾏分解,得到的四个k=1的棋盘。
但要注意这四个棋盘,并不都是与原问题相似且独⽴的⼦问题。
因为当如图中的残缺⽅格在左上部时,第1个⼦问题与原问题相似,⽽右上⾓、左下⾓和右下⾓三个⼦棋盘(也就是图中标识为2、3、4号⼦棋盘),并不是原问题的相似⼦问题,⾃然也就不能独⽴求解了。
当使⽤⼀个①号三格板覆盖2、3、4号三个⼦棋盘的各⼀个⽅格后,我们把覆盖后的⽅格,也看作是残缺⽅格(称为“伪”残缺⽅格),这时的2、3、4号⼦问题就是独⽴且与原问题相似的⼦问题了。
• 问题分析从以上例⼦还可以发现当残缺⽅格在第1个⼦棋盘,⽤①号三格板覆盖其余三个⼦棋盘的交界⽅格,可以使另外三个⼦棋盘转化为独⽴⼦问题;当残缺⽅格在第2个⼦棋盘时,则⾸先⽤②号三格板进⾏棋盘覆盖当残缺⽅格在第3个⼦棋盘时,则⾸先⽤③号三格板进⾏棋盘覆盖当残缺⽅格在第4个⼦棋盘时,则⾸先⽤④号三格板进⾏棋盘覆盖,这样就使另外三个⼦棋盘转化为独⽴⼦问题。
程序代码思路:表⽰⽅法:每个三格板需要⽤同⼀个数字表⽰,不同三格板编号不同。
源码:#include <iomanip>using namespace std;int board[100][100]; //存放棋盘L 型的标号数组;int tile=1; // L 型⾻牌号void chessBoard(int tr, inttc, int dr, int dc, int size){if (size==1)return; int t = tile++; // L 型⾻牌号 int s = size/2; // 分割棋盘//________________________________________________ 覆盖左上⾓分治递归执⾏步骤: 1)chessBoard(0, 0, 0, 0, 4); { t=1; s=2; chessBoard(0, 0, 0, 0, 2); { t=2; s=1; chessBoard(0, 0, 0, 0, 1); { s==1 return}以下三步将左上⾓三格板⽤t=2覆盖 }return以下三步对右上递归先⽤t=1 覆盖左下左下递归先⽤t=1 覆盖右上右下递归先⽤t=1 覆盖左上递归处理类似。
用python代码编写象棋界面,棋盘覆盖问题
⽤python代码编写象棋界⾯,棋盘覆盖问题编写象棋界⾯import turtlet=turtle.Pen()t.speed(100)def angle(x,y):t.penup()t.goto(x+3,y+3)t.pendown()t.setheading(0)t.forward(5)t.goto(x+3,y+3)t.left(90)t.forward(5)t.penup()t.goto(x+3,y-3)t.pendown()t.setheading(0)t.forward(5)t.goto(x+3,y-3)t.left(90)t.forward(-5)t.penup()t.goto(x-3,y+3)t.pendown()t.setheading(0)t.forward(-5)t.goto(x-3,y+3)t.left(90)t.forward(5)t.penup()t.goto(x-3,y-3)t.pendown()t.setheading(0)t.forward(-5)t.goto(x-3,y-3)t.left(90)t.forward(-5)def v(x,y):t.penup()t.goto(x+3,y+3)t.pendown()t.setheading(0)t.forward(5)t.goto(x+3,y+3)t.left(90)t.forward(5)t.penup()t.goto(x+3,y-3)t.pendown()t.setheading(0)t.forward(5)t.goto(x+3,y-3)t.left(90)t.forward(-5)t.penup()def a(x,y):t.penup()t.goto(x-3,y+3)t.pendown()t.setheading(0)t.forward(-5)t.goto(x-3,y+3)t.left(90)t.forward(5)t.penup()t.goto(x-3,y-3)t.pendown()t.setheading(0)t.forward(-5)t.goto(x-3,y-3)t.left(90)t.forward(-5)#1.绘制所有横线t.penup()t.goto(-80,90)t.pendown()for i in range(1,6,1):t.forward(160)t.forward(20)t.right(90)t.pendown()t.forward(160)t.penup()t.left(90)t.forward(20)t.left(90)t.pendown()#2.绘制所有竖线t.left(90)t.penup()t.forward(20)t.pendown()for i in range(1,5,1):t.forward(80)t.penup()t.forward(20)t.pendown()t.forward(80)t.right(90)t.forward(20)t.right(90)t.forward(80)t.penup()t.forward(20)t.pendown()t.forward(80)t.left(90)t.forward(20)t.left(90)t.forward(180)t.left(90)t.forward(160)t.left(90)t.forward(180)#3.绘制斜线t.left(90)t.forward(60)t.left(45)t.forward(40*1.414)t.left(45)t.forward(-40)t.left(45)t.forward(40*1.414)t.penup()t.goto(-20,90)t.pendown()t.right(180)t.forward(40*1.414)t.right(45)t.forward(-40)t.right(45)t.forward(40*1.414)#4.绘制炮和兵的位置angle(60,50)angle(-60,50)angle(60,-50)angle(-60,-50)angle(40,30)angle(-40,30)angle(40,-30)angle(-40,-30)angle(0,30)angle(0,-30)a(80,30)a(80,-30)v(-80,-30)v(-80,30)#5.绘制外围线绘制⼀个长⽅形,设置笔的粗细t.penup()t.goto(-90,-100)t.pendown()t.pensize(10)t.forward(200)t.right(90)t.forward(180)t.right(90)t.forward(200)t.right(90)棋盘覆盖问题在2^k*2^k个⽅格组成的棋盘中,有⼀个⽅格被占⽤,⽤下图的4种L型⾻牌覆盖所有棋盘上的其余所有⽅格,不能重叠。
棋盘覆盖问题的算法实现(代码及截图)
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); } } void main() { int i,j,k,a,b; printf("请输入特殊方格的坐标:"); scanf("%d %d",&a,&b); ChessBoard(0,0,a,b,4); for(k=0;k<tile;k++) { printf("编号为%d的型骨牌的坐标为:",k); for(i=0;i<4;i++) for(j=0;j<4;j++) { if(Board[i][j]==k&&(i!=a||j!=b)) printf("(%d,%d)",i,j); } printf("\n"); } }
棋盘覆盖问题的算法实现
在一个2^k * 2^k个方格组成的棋盘中,有一个方格与其它的 不同,若使用以下四种L型骨牌覆盖除这个特殊方格的其它方 格,如何覆盖。 四个L型骨牌如下图1
棋盘划分----分治算法
棋盘划分----分治算法题⽬:在⼀个2k×2k个⽅格组成的棋盘中,恰有⼀个⽅格与其他⽅格不同,称该⽅格为⼀特殊⽅格,且称该棋盘为⼀特殊棋盘。
在棋盘覆盖问题中,要⽤图1的4种不同形态的L型⾻牌覆盖给定的特殊棋盘上除特殊⽅格以外的所有⽅格,且任何2个L型⾻牌不得重叠覆盖。
图1 k=2的棋盘和 4个L型⾻牌算法:当k>0时,将2k×2k棋盘分割为4个2k-1×2k-1 ⼦棋盘图2(a)所⽰。
特殊⽅格必位于4个较⼩⼦棋盘之⼀中,其余3个⼦棋盘中⽆特殊⽅格。
为了将这3个⽆特殊⽅格的⼦棋盘转化为特殊棋盘,可以⽤⼀个L型⾻牌覆盖这3个较⼩棋盘的会合处,如图2(b)所⽰,从⽽将原问题转化为4个较⼩规模的棋盘覆盖问题。
递归地使⽤这种分割,直⾄棋盘⼤⼩为1×1。
图2⽤简单的话来描述,就是把2k的棋盘划分为2k-1个2*2的⼦棋盘,由于算法在划分时会再每⼀个⽅块中占据⼀个⽅格,所以每个2*2的⼦棋盘只有3个格⼦是没有被覆盖的,⽽恰好使⽤题⽬提供的L型⾻牌进⾏覆盖。
核⼼代码:/*输⼊:hr,hc为矩阵顶点坐标fr,fc为特殊格所在坐标size为当前矩阵边长*/void hf(int hr,int hc,int fr,int fc,int size){//如果size为1,则证明已经分的不能再分了if(size == 1){return;}int t = tile++;//分割棋盘int s = size/2;//当特殊格在当前所分的第⼀象限if(fr<hr+s && fc< hc+s){hf(hr,hc,fr,fc,s);}//当特殊格没在当前所分的第⼀象限是,对右下⾓做特殊格else{*(*(qp+hr+s-1)+hc+s-1) = t;//2表⽰特殊格hf(hr,hc,hr+s-1,hc+s-1,s);}//当特殊格在当前所分的第⼆象限if(fr<hr+s && fc>= hc+s){hf(hr,hc+s,fr,fc,s);}//当特殊格没在当前所分的第⼆象限是,对左下⾓做特殊格else{*(*(qp+hr+s-1)+hc+s) = t;hf(hr,hc+s,hr+s-1,hc+s,s);}//当特殊格在当前所分的第3象限if(fr>=hr+s && fc< hc+s){hf(hr+s,hc,fr,fc,s);}//当特殊格没在当前所分的第3象限是,对右上⾓做特殊格else{*(*(qp+hr+s)+hc+s-1) = t;hf(hr+s,hc,hr+s,hc+s-1,s);}//当特殊格在当前所分的第4象限if(fr>=hr+s && fc>= hc+s){hf(hr+s,hc+s,fr,fc,s);}//当特殊格没在当前所分的第4象限是,对左上⾓做特殊格else{*(*(qp+hr+s)+hc+s) = t;hf(hr+s,hc+s,hr+s,hc+s,s);}}运⾏结果:当/*LENGH的⼤⼩为2^xSPECIALX,SPECIALY为特殊格的坐标*/#define LENGTH 2#define SPECIALX 1#define SPECIALY 1时当/*LENGH的⼤⼩为2^xSPECIALX,SPECIALY为特殊格的坐标*/#define LENGTH 8#define SPECIALX 1#define SPECIALY 1/*时结果分析:程序能在限制条件下正确的进⾏⾻牌覆盖棋盘。
棋盘覆盖实验报告心得(3篇)
第1篇一、实验背景棋盘覆盖实验是计算机科学中一个经典的算法问题,旨在研究如何用最少数量的棋子覆盖整个棋盘。
这个实验不仅考验了我们对算法和数据结构的理解,还锻炼了我们的逻辑思维和编程能力。
在本实验中,我选择了使用回溯算法来解决棋盘覆盖问题,以下是我在实验过程中的心得体会。
二、实验目的1. 理解棋盘覆盖问题的背景和意义;2. 掌握回溯算法的基本原理和应用;3. 提高编程能力和逻辑思维能力;4. 分析不同算法的优缺点,为实际应用提供参考。
三、实验过程1. 确定问题模型棋盘覆盖问题可以抽象为一个二维数组,其中每个元素代表棋盘上的一个格子。
我们需要使用棋子(如皇后)来覆盖整个棋盘,使得每个格子都被至少一个棋子覆盖。
在本实验中,我们选择使用N皇后问题作为棋盘覆盖问题的子问题。
2. 设计算法为了解决棋盘覆盖问题,我们可以采用回溯算法。
回溯算法的基本思想是从一个解空间中搜索解,当找到一个解时,将其输出;当发现当前解不满足条件时,回溯到上一个状态,尝试其他可能的解。
具体步骤如下:(1)初始化棋盘,将所有格子设为未覆盖状态;(2)从第一行开始,尝试将棋子放置在该行第一个格子;(3)判断放置棋子后是否满足约束条件,如冲突、越界等;(4)如果满足约束条件,将该格子设为已覆盖状态,继续放置下一行棋子;(5)如果当前行已放置完棋子,检查是否覆盖了整个棋盘;(6)如果覆盖了整个棋盘,输出解;否则,回溯到上一个状态,尝试其他可能的解。
3. 编写代码根据上述算法,我使用Python语言实现了棋盘覆盖问题的回溯算法。
在代码中,我定义了一个二维数组来表示棋盘,并实现了放置棋子、检查约束条件、回溯等功能。
4. 实验结果与分析通过实验,我发现以下结论:(1)随着棋盘大小的增加,回溯算法的搜索空间也随之增大,导致算法的运行时间显著增加;(2)在解决N皇后问题时,当棋盘较大时,回溯算法的效率较低;(3)通过优化算法,如剪枝,可以提高算法的效率。
关于棋盘覆盖问题的算法(C++) [当文网提供]
分治法解决棋盘覆盖问题By Aillo on April 9, 2008 10:22 PM |0 Comments | Previous | Next | EDIT在一个2k x 2k ( 即:2^k x 2^k )个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。
在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
这里我们用分治法解决该问题。
分治法是把一个规模很大的问题分解为多个规模较小、类似的子问题,然后递归地解决所有子问题,最后再由子问题的解决得到原问题的解决。
【解题思路】:将2^k x 2^k的棋盘,先分成相等的四块子棋盘,其中特殊方格位于四个中的一个,构造剩下没特殊方格三个子棋盘,将他们中的也假一个方格设为特殊方格。
如果是:左上的子棋盘(若不存在特殊方格)----则将该子棋盘右下角的那个方格假设为特殊方格右上的子棋盘(若不存在特殊方格)----则将该子棋盘左下角的那个方格假设为特殊方格左下的子棋盘(若不存在特殊方格)----则将该子棋盘右上角的那个方格假设为特殊方格右下的子棋盘(若不存在特殊方格)----则将该子棋盘左上角的那个方格假设为特殊方格当然上面四种,只可能且必定只有三个成立,那三个假设的特殊方格刚好构成一个L型骨架,我们可以给它们作上相同的标记。
这样四个子棋盘就分别都和原来的大棋盘类似,我们就可以用递归算法解决。
代码如下:#include<iostream.h>int tile=1;int board[100][100];void chessBoard(int tr, int tc, int dr, int dc, int size) {if(size==1)return;int t=tile++;int 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);}}void main(){int size;cout<<"输入棋盘的size(大小必须是2的n次幂): ";cin>>size;int index_x,index_y;cout<<"输入特殊方格位置的坐标: ";cin>>index_x>>index_y;chessBoard(0,0,index_x,index_y,size);for(int i=0;i<size;i++){for(int j=0;j<size;j++)cout<<board[i][j]<<"\t";cout<<endl;}}关于棋盘覆盖问题的算法(C++)//程序说明:1):讲一下代码拷贝到vc6.0(或其他支持的IDE环境)下,执行后会生成一个// input.txt文件,打开将里面的参数换成你想设计的再执行程序就OK了!// 2):如果对代码理解不透,建议使用但不调试,检测每一步的执行情况// 3):本程序仅供学习参考使用,用完请删除#include<stdio.h>#include<fstream.h>#include<iomanip.h>#include<iostream.h>#include<stdlib.h>int tile=0; //定义全局变量tile表示L型骨牌编号int **chessarr; //定义全局变量chessarr表示棋盘数组void chessboard(int row0,int col0,int size,int sprow,int spcol);// 棋盘覆盖函数// row0,col0为棋盘左上角位置,sprow,spcol为特殊方格位置// size为棋盘规模void chessboard(int row0,int col0,int size,int sprow,int spcol) //棋盘覆盖函数{if(size==1) return; //如果棋盘规模=1,返回int s=size/2; //分割棋盘int t=++tile; //L型骨牌编号加1//处理左上角子棋盘if(sprow < row0+s && spcol < col0+s)chessboard(row0,col0,s,sprow,spcol);else{chessarr[row0+s-1][col0+s-1]=t;chessboard(row0,col0,s,row0+s-1,col0+s-1);}//处理右上角子棋盘if(sprow < row0+s && spcol >= col0+s)chessboard(row0,col0+s,s,sprow,spcol);else{chessarr[row0+s-1][col0+s]=t;chessboard(row0,col0+s,s,row0+s-1,col0+s);}//处理左下角子棋盘if(sprow >= row0+s && spcol < col0+s)chessboard(row0+s,col0,s,sprow,spcol);else{chessarr[row0+s][col0+s-1]=t;chessboard(row0+s,col0,s,row0+s,col0+s-1);}//处理右下角子棋盘if(sprow >= row0+s && spcol >= col0+s)chessboard(row0+s,col0+s,s,sprow,spcol);else{chessarr[row0+s][col0+s]=t;chessboard(row0+s,col0+s,s,row0+s,col0+s);}}void main(){int k,x,y; //阶数及特殊点位置int i,j,n; //棋盘规模为n*nifstream in("input.txt"); //打开输入文件if(in.fail()){cout << "the input.txt is not exist!";exit(1);}in>>k>>x>>y; //读入阶数k和特殊方格位置in.close(); //关闭输入文件if (k<1){cout << "K<1, Error input.txt!";exit (1);}for (i=0,n=1;i<k;i++)n*=2;//在堆内存中建立棋盘数组,填充特殊方格if((chessarr=new int*[n])==NULL){cout << "Can't allocate more memory,terminating." << endl;exit (1);}for (i=0;i<n;i++ ){if((chessarr[i]=new int[n])==NULL){cout << "Can't allocate more memory,terminating." << endl;exit (1);}}chessarr[x-1][y-1]=0; // 填写特殊方格tile=0;chessboard(0,0,n,x-1,y-1);//进行棋盘覆盖,左上角位置0,0; 棋盘宽度n; 特殊点x,y ofstream out("output.txt"); //创建输出文件//同时输出到文件和屏幕for (i=0;i<n;i++){for (j=0;j<n;j++ ){out << setw(5) << chessarr[i][j];cout << setw(5) << chessarr[i][j];}out << endl;cout << endl;}out.close(); //关闭输出文件//释放内存for(i=0;i<n;i++)delete[] chessarr[i];delete[] chessarr;return;}矩阵快速乘法矩阵相乘在3D变换中是被频繁用到的一种计算,但在矩阵相乘过程中用到了大量的乘法运算,而cpu中运算单元对于乘法的效率是比较低的,远低于加法运算,所以,如果能找到一种用加法来替代乘法的方法实现矩阵相乘,将能大大提高我们程序的效率。
棋盘覆盖问题
分治法棋盘覆盖声明:本文使用的代码和例子的来源:《计算机算法设计与分析》(王晓东编著,电子工业出版社)。
我对代码做了少许修改,使可以在tc的图形模式下看到题目的结果。
题目:在一个(2^k)*(2^k)个方格组成的棋盘上,有一个特殊方格与其他方格不同,称为特殊方格,称这样的棋盘为一个特殊棋盘。
现在要求对棋盘的其余部分用L型方块填满(注:L 型方块由3个单元格组成。
即围棋中比较忌讳的愚形三角,方向随意),切任何两个L型方块不能重叠覆盖。
L型方块的形态如下:■■■■■■■,■ ,■■ ,■■题目的解法使用分治法,即子问题和整体问题具有相同的形式。
我们对棋盘做一个分割,切割一次后的棋盘如图1所示,我们可以看到棋盘被切成4个一样大小的子棋盘,特殊方块必定位于四个子棋盘中的一个。
假设如图1所示,特殊方格位于右上角,我们把一个L型方块(灰色填充)放到图中位置。
这样对于每个子棋盘又各有一个“特殊方块”,我们对每个子棋盘继续这样分割,知道子棋盘的大小为1为止。
用到的L型方块需要(4^k-1)/3 个,算法的时间是O(4^k),是渐进最优解法。
本题目的C语言的完整代码如下(TC2.0下调试),运行时,先输入k的大小,(1<=k< =6),然后分别输入特殊方格所在的位置(x,y), 0<=x,y<=(2^k-1)。
程序将绘制出覆盖后的棋盘,运行效果截图如图2所示。
[此程序在TC下课成功运行。
VC下缺少头文件<graphics.h>,编译时会出现错误。
]#include <stdio.h>#include <graphics.h>/*#include <cpyscr.h>*/#define N 64#define BoardLeft 2#define BoardTop 2int Board[N][N]; /*棋盘*/int tile;/*全局性质的L图形编号*/int CellSize=10;/*网格大小*/int BorderColor=LIGHTGRAY;/*用指定颜色填充一个单元格!*/void PutCell(int x,int y,int color){setfillstyle(SOLID_FILL,color);rectangle(BoardLeft+x*CellSize,BoardTop+y*CellSize,BoardLeft+(x+1) *CellSize,BoardTop+(y+1)*CellSize);floodfill(BoardLeft+x*CellSize+CellSize/2,BoardTop+y*CellSize+Cel lSize/2,BorderColor);}/*绘制L方块,(cx,cy)是L方块的中心点CELL坐标,pos从1到4,表示位于特殊方块位于哪个角(即缺失的一角位置)*/void PutBlock(int cx,int cy,int pos){int x,y,t=CellSize;/*方块起始点像素坐标*/x=BoardLeft+cx*CellSize;y=BoardTop+cy*CellSize;moveto(x,y);/*移动到中心点*/switch(pos){case 1:/*左上角缺*/lineto(x,y-t);lineto(x+t,y-t);lineto(x+t,y+t);lineto(x-t,y+t);lineto(x-t,y);break;case 2:/*右上角缺*/lineto(x+t,y);lineto(x+t,y+t);lineto(x-t,y+t);lineto(x-t,y-t);lineto(x,y-t);break;case 3:/*左下角缺*/lineto(x-t,y);lineto(x-t,y-t);lineto(x+t,y-t);lineto(x+t,y+t);lineto(x,y+t);break;case 4:/*右下角缺*/lineto(x,y+t);lineto(x-t,y+t);lineto(x-t,y-t);lineto(x+t,y-t);lineto(x+t,y);break;}lineto(x,y);/*回到闭合点!*/}/*初始化图形模式*/void InitGraph(){int gdriver=DETECT,gmode;initgraph(&gdriver,&gmode,"");setcolor(BorderColor);}/*关闭图形模式*/void CloseGraph(){closegraph();}/*打印棋盘*/void PrintBoard(int size){int i,j;clrscr();for(j=0;j<size;j++){for(i=0;i<size;i++){printf("%2d ",Board[i][j]);}printf("\n");}printf("\n--------------------------------\n");printf("size=%d;\n");}/*left,top:方块的左上角坐标,x,y:特殊方块的坐标 size:当前的子棋盘大小*/void ChessBoard(int left,int top,int x,int y,int size){int i,t,s,pos;/*t是方块的编号,s是棋盘的一半尺寸!(size/2),pos表示方块位于哪一角 */if(size==1)return;t=tile++;/*当前L行方块的编号!递增*/s=size/2;/*------------处理左上角----------*/if(x<left+s && y<top+s){ChessBoard(left,top,x,y,s);/*设置位于左上角的标识*/ pos=1;}else{Board[left+s-1][top+s-1]=t; /*不在左上角*/ ChessBoard(left,top,left+s-1,top+s-1,s);}/*------------处理右上角----------*/if(x>=left+s && y<top+s){ChessBoard(left+s,top,x,y,s);pos=2;}else{Board[left+s][top+s-1]=t;/*不在右上角*/ChessBoard(left+s,top,left+s,top+s-1,s);}/*------------处理左下角----------*/if(x<left+s && y>=top+s){ChessBoard(left,top+s,x,y,s);pos=3;}else{Board[left+s-1][top+s]=t;ChessBoard(left,top+s,left+s-1,top+s-1,s);}/*------------处理右下角----------*/if(x>=left+s && y>=top+s){ChessBoard(left+s,top+s,x,y,s);pos=4;}else{Board[left+s][top+s]=t;ChessBoard(left+s,top+s,left+s,top+s,s);}/*画出当前的L方块*/PutBlock(left+s,top+s,pos);}void main(){int size,k,x,y,i,j;printf("please input k=? (k should not more than 6, boardsize=2^k ): \n");scanf("%d",&k);size=1<<k;printf("please input position of the special cell. x=? (not more than %d): \n",size-1);scanf("%d",&x);printf("please input position of the special cell. y=? (not more than %d): \n",size-1);scanf("%d",&y);if(k<0 || k>6 || x<0 || x>(size-1) || y<0 || y>(size-1)){printf("Input invalid!\n");return;}InitGraph();tile=1;Board[x][y]=0;/*绘制特殊方块!*/PutCell(x,y,RED);ChessBoard(0,0,x,y,size);/*CopyScreen("c:\\tc\\temp\\chess.bmp",0,0,400,400);*/getch();CloseGraph();}2.#include"stdio.h"#include<graphics.h>#include<dos.h>#include<math.h>int tile=1;int avg;int basex,basey;void chessboard(int tr,int tc,int dr,int dc,int size)/*加了一个int tc*/{int s,t;if(size==1)return;t=tile++;s=size/2;delay(150000);setfillstyle(7,1);sound(500);delay(1500);sound(400);delay(1500);nosound();bar(dr*avg+basex,dc*avg+basey,(dr+1)*avg+basex,(dc+1)*avg+basey);if((dr*avg+basex)<tr+s*avg&&(dc*avg+basey)<tc+s*avg)chessboard(tr,tc,dr,dc,s);else{setfillstyle(1,t);bar(tr+(s-1)*avg,tc+(s-1)*avg,tr+s*avg,tc+s*avg);chessboard(tr,tc,(tr-basex)/avg+s-1,(tc-basey)/avg+s-1,s);}if((dr*avg+basex)<tr+s*avg&&(dc*avg+basey)>=tc+s*avg)chessboard(tr,tc+s*avg,dr,dc,s);else{setfillstyle(1,t);bar(tr+(s-1)*avg,tc+s*avg,tr+s*avg,tc+(s+1)*avg);/*在这加了一个tr+ s*avg*/chessboard(tr,tc+s*avg,(tr-basex)/avg+s-1,(tc-basey)/avg+s,s); }if((dr*avg+basex)>=tr+s*avg&&(dc*avg+basey)<tc+s*avg)chessboard(tr+s*avg,tc,dr,dc,s);else{setfillstyle(1,t);bar(tr+s*avg,tc+(s-1)*avg,tr+(s-1)*avg,tc+s*avg);chessboard(tr+s*avg,tc,(tr-basex)/avg+s,(tc-basey)/avg+s-1,s); }if((dr*avg+basex)>=tr+s*avg&&(dc*avg+basey)>=tc+s*avg)chessboard(tr+s*avg,tc+s*avg,dr,dc,s);else{setfillstyle(1,t);bar(tr+s*avg,tc+s*avg,tr+(s+1)*avg,tc+(s+1)*avg);chessboard(tr+s*avg,tc+s*avg,(tr-basex)/avg+s,(tc-basey)/avg+s,s);}}main(){int size,k;int dr,dc,tr,tc;int endx,endy;int i;double x,y;int gdriver=DETECT;int gmode=VGA;initgraph(&gdriver,&gmode,"");basex=300,basey=100;endx=basex+320;endy=basey+320;cleardevice();setcolor(12);settextstyle(2,0,8);outtextxy(20,20,"zhoumingjiang\n");/*改成了outtextxy函数~~*/ outtextxy(60,60,"designer:zhoumingjiang 25/10/2002");setbkcolor(BLACK);setcolor(RED);printf("\n\n\n");printf(" please input k: ");scanf("%d",&k);x=2;y=k;size=pow(x,y);avg=320/size;rectangle(basex,basey,endx,endy);for(i=0;i<=size;i++){setlinestyle(1,1,6);line(basex,basey+i*avg,endx,basey+i*avg);line(basex+i*avg,basey,basex+i*avg,endy);}printf(" please input dr,dc: ");scanf("%d,%d",&dc,&dr);tr=basex;tc=basey;chessboard(tr,tc,dr,dc,size);}3.棋盘覆盖(C语言)#include <stdio.h>#include <conio.h>#include <math.h>int title=1;int board[64][64];void chessBoard(int tr,int tc,int dr,int dc,int size) {int s,t;if(size==1) return;t=title++;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);}}void main(){ int dr=0,dc=0,s=1,i=0,j=0;printf("print in the size of chess:\n"); scanf("%d",&s);printf("print in specal point x,y:\n"); scanf("%d%d",&dr,&dc);if(dr<s && dc<s){chessBoard(0,0,dr,dc,s);for(i=0;i<s;i++){for(j=0;j<s;j++){printf("%4d",board[i][j]);}printf("\n");}}elseprintf("the wrong specal point!!\n"); getch();}。
算法设计与分析试题及答案
1. 按分治策略求解棋盘覆盖问题时,对于如图所示的24×24的特殊棋盘,共需要多少个L 型骨牌;并在棋盘上填写L 型骨牌的覆盖情况。
2. 假设有7个物品,给出重量和价值。
若这些物品均不能被分割,且背包容量M =140,使用回溯方法求解此0-1背包问题。
请画出状态空间搜索树。
3. 假设有7个物品,它们的重量和价值如下表所示。
若这些物品均可以被分割,且背包容量M=140,使用贪心算法求解此背包问题。
请写出求解策略和求解过程。
W (35,30,50,60,40,10,25)p (10,40,30,50,35,40,30)4. 在给出的电路板中,阴影部分是已作了封锁标记的方格,请按照队列式分支限界法在图中确定a 到b 的最短布线方案,要求布线时只能沿直线或直角进行,在图中标出求得最优解时各方格情况。
5. 画出字符表的哈夫曼编码对应的二叉树。
6. 已知1()*()i i k k ij r r A a +=,k =1,2,3,4,5,6,r 1=5,r 2=10,r 3=3,r 4=8,r 5=5,r 6=20,r 7=6,求矩阵链积A 1×A 2×A 3×A 4×A 5×A 6的最佳求积顺序。
7. 给出城市网络图,售货员要从城市1出发,经过所有城市回到城市1,画出该问题的解空间树,描述出用优先队列式分支限界法求解时的搜索情况。
表示出优先队列、当前扩展结点等的变化情况。
8. 依据优先队列式分支限界法,求从s 点到t 点的单源最短路径,画出求得最优解的解空间树。
一、假设有7个物品,它们的重量和价值如下表所示。
若这些物品均不能被分割,且背包容量M=150,使用回溯方法求解此背包问题。
请写出状态空间搜索树(20分)。
答:按照单位效益从大到小依次排列这7个物品为:FBGDECA 。
将它们的序号分别记为1~7。
则可生产如下的状态空间搜索树。
其中各个节点处的限界函数值通过如下方式求得:【排序1分】5x =6x =7x =17分,每个节点1分】a .1501154040305035190.62540-++++⨯= 7(1,1,1,1,,0,0)8b. 1501154040305030177.560-++++⨯=7(1,1,1,1,0,,0)12c .4040305010170++++=(1,1,1,1,0,0,1)d. 1501054040303530167.560-++++⨯= 3(1,1,1,0,1,,0)4e. 150130404050353017560-++++⨯=1(1,1,0,1,1,,0)3f. 1501304040503510170.7135-++++⨯=4(1,1,0,1,1,0,)7g. 40405030160+++=(1,1,0,1,0,1,0)h. 1501404040353010146.8535-++++⨯= 2(1,1,0,0,1,1,)7i.1501254030503530167.560-++++⨯=5(1,0,1,1,1,,0)12 j. 1501454030503530157.560-++++⨯=1(0,1,1,1,1,,0)12在Q 1处获得该问题的最优解为(1,1,1,1,0,0,1),背包效益为170。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
void ChessBoard(int tr, int tc, int dr, int dc, int size)
{
if(size == 1)
return;
int t = ++tile, s = size/2;
//覆盖左上角子棋盘
if(dr<tr+s && dc<tc+s)
printf("\n");
}
}
int main()
{
ChessBoard(1, 1, 1, 2, 4);
DisplayBoard(4);
return 0;
}
说明:同一标号代表组成的,0代表非填充区域,从运行结果可以看出排列的方法。
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);
棋盘覆盖问题
代码:分治法
需要说明:
tr:棋盘左上角方格的行号
tc:棋盘左上角方格的列号
dr:特殊方格所在的行号
dc:特殊方格所在的列号
size:方形棋盘的边长
#include <iostream>
using namespace std;
const int N = 11;
int Board[N][N];
//特殊方格在此棋盘中
ChessBoard(tr, tc, Nhomakorabeadr, dc, s);
else//此棋盘无特殊方格
{
//用t号L型骨型牌覆盖右下角Board[tr+s-1][tc+s-1] = t;
//覆盖其余方格
ChessBoard(tr, tc, tr+s-1, tc+s-1, s);
}
//覆盖右上角子棋盘
else
{
Board[tr+s][tc+s] = t;
ChessBoard(tr+s, tc+s, tr+s, tc+s, s);
}
}
void DisplayBoard(int size)
{
for(int i=1; i<=size; ++i)
{
for(int j=1; j<=size; ++j)
printf("%2d ", Board[i][j]);
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)