算法分析解题报告--棋盘问题
组合数学中的棋盘问题

组合数学中的棋盘问题棋盘问题是组合数学中一个经典而又有趣的问题,它涉及到在一个n × n 的棋盘上放置一定数量的棋子并满足特定的条件。
在本文中,我们将探讨棋盘问题的一些常见形式以及解决方法。
一、八皇后问题八皇后问题是指在一个 8 × 8 的棋盘上放置 8 个皇后,并且每个皇后都不能相互攻击,即任意两个皇后不得处于同一行、同一列或同一对角线上。
这个问题可以通过回溯法来解决。
我们可以逐行放置皇后,并在每一行中使用循环判断每个格子是否满足条件。
如果满足条件,则继续递归下一行;如果不满足条件,则回溯到上一行继续判断。
当所有皇后都放置完毕时,即找到了一种解法。
二、骑士周游问题骑士周游问题是指在一个 n × n 的棋盘上,骑士按照国际象棋中骑士的移动规则进行移动,需要从起始格子出发,经过棋盘的每个格子,最终回到起始格子,且每个格子只能经过一次。
这个问题可以通过深度优先搜索或者广度优先搜索来解决。
我们可以从起始格子开始,按照骑士的移动规则依次遍历所有相邻的格子,并标记已访问的格子。
当所有格子都被访问过,并且最后的格子可以与起始格子连通,则找到了一种解法。
三、数独问题数独问题是指在一个 9 × 9 的棋盘上填入数字,使得每一行、每一列和每一个 3 × 3 的小方格中的数字都是 1 到 9 的不重复数字。
这个问题可以通过回溯法来解决。
我们可以逐格填入数字,并在每个格子中使用循环判断每个数字是否满足条件。
如果满足条件,则继续递归下一个格子;如果不满足条件,则尝试下一个数字。
当所有格子都填满时,即找到了一种解法。
四、六角形拼图问题六角形拼图问题是指在一个六角形的棋盘上,使用特定形状的六角形块填满整个棋盘。
这个问题可以通过搜索算法来解决。
我们可以从一个起始位置开始,依次尝试放置不同形状的六角形块。
每次放置块后,判断是否满足放置要求。
如果满足要求,则继续递归下一个位置;如果不满足要求,则尝试下一个形状的块。
棋盘解题报告(noip2017普及组第三题)

棋盘解题报告(noip2017普及组第三题)棋盘解题报告(noip2017普及组第三题)上次写了Linux⽤vim进⾏C++编程的配置和操作⼊门后,今天再给棋盘写个解题报告试试。
题⽬描述有⼀个m ×m的棋盘,棋盘上每⼀个格⼦可能是红⾊、黄⾊或没有任何颜⾊的。
你现在要从棋盘的最左上⾓⾛到棋盘的最右下⾓。
任何⼀个时刻,你所站在的位置必须是有颜⾊的(不能是⽆⾊的),你只能向上、下、左、右四个⽅向前进。
当你从⼀个格⼦⾛向另⼀个格⼦时,如果两个格⼦的颜⾊相同,那你不需要花费⾦币;如果不同,则你需要花费1 个⾦币。
另外,你可以花费2 个⾦币施展魔法让下⼀个⽆⾊格⼦暂时变为你指定的颜⾊。
但这个魔法不能连续使⽤,⽽且这个魔法的持续时间很短,也就是说,如果你使⽤了这个魔法,⾛到了这个暂时有颜⾊的格⼦上,你就不能继续使⽤魔法;只有当你离开这个位置,⾛到⼀个本来就有颜⾊的格⼦上的时候,你才能继续使⽤这个魔法,⽽当你离开了这个位置(施展魔法使得变为有颜⾊的格⼦)时,这个格⼦恢复为⽆⾊。
现在你要从棋盘的最左上⾓,⾛到棋盘的最右下⾓,求花费的最少⾦币是多少?输⼊输出格式输⼊格式:数据的第⼀⾏包含两个正整数m,n,以⼀个空格分开,分别代表棋盘的⼤⼩,棋盘上有颜⾊的格⼦的数量。
接下来的n ⾏,每⾏三个正整数x,y,c,分别表⽰坐标为(x,y)的格⼦有颜⾊c。
其中c=1 代表黄⾊,c=0 代表红⾊。
相邻两个数之间⽤⼀个空格隔开。
棋盘左上⾓的坐标为(1, 1),右下⾓的坐标为(m, m)。
棋盘上其余的格⼦都是⽆⾊。
保证棋盘的左上⾓,也就是(1,1)⼀定是有颜⾊的。
输出格式:输出⼀⾏,⼀个整数,表⽰花费的⾦币的最⼩值,如果⽆法到达,输出-1。
输⼊输出样例输⼊样例#1:5 71 1 01 2 02 2 13 3 13 4 04 4 15 5 0输出样例#1:8输⼊样例#2:5 51 1 01 2 02 2 13 3 15 5 0输出样例#2:-1说明输⼊输出样例1 说明从(1,1)开始,⾛到(1,2)不花费⾦币从(1,2)向下⾛到(2,2)花费1 枚⾦币从(2,2)施展魔法,将(2,3)变为黄⾊,花费2 枚⾦币从(2,2)⾛到(2,3)不花费⾦币从(2,3)⾛到(3,3)不花费⾦币从(3,3)⾛到(3,4)花费1 枚⾦币从(3,4)⾛到(4,4)花费1 枚⾦币从(4,4)施展魔法,将(4,5)变为黄⾊,花费2 枚⾦币,从(4,4)⾛到(4,5)不花费⾦币从(4,5)⾛到(5,5)花费1 枚⾦币共花费8 枚⾦币。
棋盘覆盖实验报告

棋盘覆盖实验报告棋盘覆盖实验报告引言:棋盘覆盖是一项经典的数学问题,也是计算机科学中常见的算法设计题目。
通过这个实验,我们可以深入了解棋盘覆盖问题的背景、原理和解决方法。
本文将详细介绍实验的目的、实验过程和实验结果,并对实验中遇到的问题进行探讨和分析。
一、实验目的棋盘覆盖问题是指如何用特殊形状的骨牌覆盖一个给定大小的棋盘,使得每个格子都被覆盖且不重叠。
本实验的目的是通过实际操作,理解棋盘覆盖问题的基本概念和解决方法,并通过实验结果验证算法的正确性。
二、实验过程1. 准备工作在实验开始之前,我们需要准备一个大小为2^n * 2^n的棋盘,以及L型骨牌。
棋盘可以用纸板或者绘图软件制作,L型骨牌可以用纸板剪切而成。
确保棋盘和骨牌的大小相匹配,并将骨牌标记为不同的编号以便于辨认。
2. 实验步骤(1)将棋盘分成4个大小相等的子棋盘,每个子棋盘的大小为2^(n-1) *2^(n-1)。
(2)在四个子棋盘中的一个上放置一个特殊的L型骨牌,使得骨牌覆盖子棋盘的中心格。
(3)递归地将剩下的三个子棋盘分别覆盖。
(4)重复步骤(2)和(3),直到棋盘被完全覆盖。
三、实验结果经过实验,我们成功地完成了棋盘覆盖。
通过观察实验结果,我们可以发现每个骨牌都被正确地放置在了棋盘上,且每个格子都被覆盖且不重叠。
这验证了我们所使用的算法的正确性。
四、问题探讨和分析在实验过程中,我们遇到了一些问题,对这些问题进行探讨和分析有助于更好地理解棋盘覆盖问题。
1. 子棋盘的划分问题在实验中,我们将棋盘分成了四个子棋盘,每个子棋盘的大小都是原棋盘的一半。
这种划分方式是否合理?是否存在其他划分方式?通过思考和尝试,我们可以发现,将棋盘划分为其他数量的子棋盘也是可行的,但是划分后的子棋盘大小必须是2的幂次方。
2. 骨牌的放置问题在实验中,我们使用了特殊的L型骨牌进行覆盖。
这种骨牌是否是唯一的选择?是否存在其他类型的骨牌可以完成棋盘覆盖?通过思考和实验,我们可以发现,除了L型骨牌,还存在其他形状的骨牌可以完成棋盘覆盖,但是它们的形状和数量都是有限的。
算法导论课程设计报告_棋盘移动棋子问题

一、设计内容与设计要求1.设计内容:对课程《算法导论》中的常用算法进行综合设计或应用(具体课题题目见后面的供选题目)。
2.设计要求:●课程设计报告正文内容(一)问题的描述;(二)算法设计与分析,内容包括1,算法设计,对问题的分析和算法的设计2,算法描述,以伪代码形式的算法3,算法分析,主要是算法的正确性和运行时间的分析(三)算法实现所有程序的原代码,要求用C语言程序实现,并对程序写出必要的注释。
●书写格式a.要求用A4纸打印成册b.正文格式:一级标题用3号黑体,二级标题用四号宋体加粗,正文用小四号宋体;行距为22。
c.正文的内容:正文总字数要求在3000字左右(不含程序原代码)。
G.封面格式如下页。
●考核方式指导老师负责验收程序的运行结果,并结合学生的工作态度、实际动手能力、创新精神和设计报告等进行综合考评,并按优秀、良好、中等、及格和不及格五个等级给出每位同学的课程设计成绩。
具体考核标准包含以下几个部分:a.平时出勤(占10%)b.系统需求分析、功能设计、数据结构设计及程序总体结构合理与否(占10%)c.程序能否完整、准确地运行,个人能否独立、熟练地调试程序(占40%)G.设计报告(占30%)e.独立完成情况(占10%)。
注意:不得抄袭他人的报告(或给他人抄袭),一旦发现,成绩为零分。
课程验收要求a.判定算法设计的合理性,运行相关程序,获得正确的数值结果。
b.回答有关问题。
c.提交课程设计报告。
G.提交软盘(源程序、设计报告文档)。
e.依内容的创新程度,完善程序情况及对程序讲解情况打分。
一、问题描述(一)问题的描述假设有一张n*n个方格的棋盘以及一个棋子。
必须根据以下的规则把棋子从棋盘的底边移动到棋盘的顶边。
在每一步你可以把棋子移动到三个方格中的一个:1) 正上方的方格2) 左上方的方格(只能当这个棋子不在最左列的时候)3) 右上方的方格(只能当这个棋子不在最右列的时候)每移动到一个方格就会得到相应方格内的钱。
算法设计与分析实验报告棋盘覆盖问题

算法设计与分析实验报告棋盘覆盖问题贵州大学计算机科学与技术学院计算机科学与技术系上机实验报告课程名称:算法设计与分析班级:信计101班实验日期:2013-9-30 姓名: 张胜学号:1007010162 指导教师:程欣宇实验序号:一实验成绩: 一、实验名称分治算法实验 - 棋盘覆盖问题二、实验目的及要求1、熟悉递归算法编写;2、理解分治算法的特点;3、掌握分治算法的基本结构。
三、实验环境Visual C++四、实验内容根据教材上分析的棋盘覆盖问题的求解思路,进行验证性实验;要求完成棋盘覆盖问题的输入、分治求解、输出。
有余力的同学尝试消去递归求解。
五、算法描述及实验步骤分治算法原理:分治算法将大的分解成形状结构相同的子问题,并且不断递归地分解,直到子问题规模小到可以直接求解。
棋盘覆盖问题描述:在一个2k x 2k个方格组成的棋盘中恰有一个方格与其他的不同称为特殊方格,想要求利用四种L型骨牌(每个骨牌可覆盖三个方格)不相互重叠覆盖的将除了特殊方格外的其他方格覆盖。
实验步骤:1、定义用于输入和输出的数据结构;2、完成分治算法的编写;3、测试记录结构;4、有余力的同学尝试不改变输入输出结构,将递归消除,并说明能否不用栈,直接消除递归,为什么,六、调试过程及实验结果实验运行结果:七、总结通过本次实验,我更深的理解了递归和分治策略。
代码是书上的算法,加上主函数就行了,用的是C语言编写,很长时间没用了,感觉有点生疏。
实验结果有点问题,就是覆盖棋盘时,并不是按照1,2,3….的字符顺序,而是按照很乱的顺序输出字符,这个我不知道怎么解决,就没解决。
八、附录#include "stdio.h"#include "conio.h"int board[8][8] ={{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0 ,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}};int tile=0;void chessBoard(int tr, int tc, int dr, intdc, int size){int t=tile++,s=size/2;if (size==1) return;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);} }main(){int i ,j;chessBoard(0,0,5,5,8);for(i=0;i <8;i++){for( j=0;j <8;j++) {if(board[i][j]<10)printf("0");printf("%d",board[i][j]);printf(" ");}printf( "\n"); } getchar();}。
分治法棋盘覆盖

算法分析与设计实验报告—分治法解决棋盘覆盖问题一、实验目的建立算法复杂度的理论分析与实验分析的联系,深刻体会算法复杂度作为算法的好坏评价指标的本质含义。
二、实验要求1、用c++程序语言实现分治法解决棋盘覆盖问题。
2、分析算法的时间复杂度三、实验原理用分治策略,可以设计解决棋盘问题的一个简介算法。
当k>0时,可以将2^k *2^k棋盘分割为4个2^k-1 * 2^k-1子棋盘。
由棋盘覆盖问题得知,特殊方格必位于4个较小的子棋盘中,其余3个子棋盘中无特殊方格。
为了将3个无特殊方格的子棋盘转化为特殊棋盘可以将一个L型骨牌覆盖这3个较小棋盘的会合处,所以,这3个子棋盘上被L型覆盖的方格就成为给棋盘上的特殊方格,从而将原问题转化为4个较小规模的棋盘覆盖问题。
递归的使用这种分割,直至棋盘简化为1*1棋盘为止。
四、实验过程(步骤)1、数据说明:tr:棋盘上左上角方格的行号tc:棋盘上左上角方格的列号dr:特殊方格所在的行号dc:特殊方格所在的列号定义了全局变量tile,用于进行覆盖。
区分4种不同L类型的骨牌,初始值为0.Board[]数组用来表示棋盘2、函数说明ChessBoard函数实现了递归的将棋盘划分为子棋盘,并将棋盘进行覆盖。
main()函数用来进行输入棋盘的大小和特殊棋盘的位置。
使用memset(Board,0,sizeof(Board))将Board[]数组清零使用setw()函数控制输出格式五、运行结果六、实验分析与讨论设T(n)是算法ChessBoard覆盖一个2^k * 2^k棋盘所需要的时间,则从算法的分治策略可知,T(k)满足如下递归方程:O(1)k = 0T(k) = {4T(k-1)+O(1)k>0解得此递归方程可得T(k) = O(4^k)。
由于覆盖一个2^k *2^k棋盘所需的L型骨牌个数为(4^k —1)/3,故算法ChessBoard是一个在渐进意义下最优的算法七、实验心得通过这次试验,更多的了解了分治法解题的思路就是将大问题化为若干子问题,再依次解决子问题,最后获得问题的答案。
分治策略算法棋盘覆盖问题
在一个2^k * 2^k个方格组成的棋盘中,有一个方格与其它的不同,若使用以下四种L型骨牌覆盖除这个特殊方格的其它方格,如何覆盖。
四个L型骨牌如下图1图1棋盘中的特殊方格如图2图2实现的基本原理是将2^k * 2^k的棋盘分成四块2^(k - 1) * 2^(k - 1)的子棋盘,特殊方格一定在其中的一个子棋盘中,如果特殊方格在某一个子棋盘中,继续递归处理这个子棋盘,直到这个子棋盘中只有一个方格为止如果特殊方格不在某一个子棋盘中,将这个子棋盘中的相应的位置设为骨牌号,将这个无特殊方格的了棋盘转换为有特殊方格的子棋盘,然后再递归处理这个子棋盘。
原理如图3所示。
图3将棋盘保存在一个二维数组中。
骨牌号从1开始,特殊方格为0,如果是一个4 * 4的棋盘,特殊方格为(2,2),那么程序的输出为2 23 32 1 1 34 1 0 54 45 5相同数字的为同一骨牌。
下面是棋盘覆盖问题的c++语言实现。
#include <iostream>#include<iomanip>using namespace std;#define BOARD_SIZE 4int board[BOARD_SIZE][BOARD_SIZE];// c1, r1: 棋盘左上角的行号和列号// c2, r2: 特殊方格的行号和列号// size = 2 ^ kvoid chessboard(int r1, int c1, int r2, int c2, int size){if(1 == size) return;int half_size;static int domino_num = 1;int d = domino_num++;half_size = size / 2;if(r2 < r1 + half_size && c2 < c1 + half_size) //特殊方格在左上角子棋盘chessboard(r1, c1, r2, c2, half_size);else // 不在此棋盘,将此棋盘右下角设为相应的骨牌号{ board[r1 + half_size - 1][c1 + half_size - 1] = d;chessboard(r1, c1, r1 + half_size - 1, c1 + half_size - 1, half_size);}if(r2 < r1 + half_size && c2 >= c1 + half_size) //特殊方格在右上角子棋盘chessboard(r1, c1 + half_size, r2, c2, half_size);else // 不在此棋盘,将此棋盘左下角设为相应的骨牌号{ board[r1 + half_size - 1][c1 + half_size] = d;chessboard(r1, c1 + half_size, r1 + half_size - 1, c1 + half_size, half_size);}if(r2 >= r1 + half_size && c2 < c1 + half_size) //特殊方格在左下角子棋盘chessboard(r1 + half_size, c1, r2, c2, half_size);else // 不在此棋盘,将此棋盘右上角设为相应的骨牌号{ board[r1 + half_size][c1 + half_size - 1] = d;chessboard(r1 + half_size, c1, r1 + half_size, c1 + half_size - 1, half_size);}if(r2 >= r1 + half_size && c2 >= c1 + half_size) //特殊方格在左上角子棋盘chessboard(r1 + half_size, c1 + half_size, r2, c2, half_size);else // 不在此棋盘,将此棋盘左上角设为相应的骨牌号{ board[r1 + half_size][c1 + half_size] = d;chessboard(r1 + half_size, c1 + half_size, r1 + half_size, c1 + half_size, half_size);}}void main(){ int i, j;board[2][2] = 0;chessboard(0, 0, 2, 2, BOARD_SIZE);for(i = 0; i < BOARD_SIZE; i++){ for(j = 0; j < BOARD_SIZE; j++)cout<<setw(4)<<board[i][j];cout<<"\n";}}。
棋盘问题回溯求解算法
棋盘问题回溯求解算法1. 引言回溯法是一种用于解决组合问题的算法,它通过尝试所有可能的解决方案来找到满足特定条件的解。
棋盘问题是一类经典的组合问题,其目标是在一个棋盘上放置特定数量的棋子,使得它们满足一定的规则。
本文将介绍如何使用回溯法来求解棋盘问题。
2. 棋盘问题的定义棋盘问题通常是指在一个正方形棋盘上放置特定数量的棋子,使得它们满足特定规则。
常见的棋盘问题有八皇后问题、马踏棋盘问题等。
以八皇后问题为例,其规则是:在一个8x8的棋盘上放置8个皇后,使得每个皇后都不会互相攻击。
皇后可以攻击同一行、同一列或同一对角线上的其他皇后。
3. 回溯法求解棋盘问题回溯法是一种递归的搜索算法,它通过尝试所有可能的选择来找到满足条件的解。
具体步骤如下:1.定义一个数据结构来表示当前状态,例如使用一个数组来表示棋盘的布局。
2.从问题的起始状态开始,尝试所有可能的选择。
对于每一个选择,判断是否满足问题的约束条件。
3.如果当前选择满足约束条件,则将其添加到解空间中,并继续递归地探索下一个状态。
4.如果当前选择不满足约束条件,则回溯到上一个状态,并尝试下一个选择。
5.当所有的选择都被尝试完毕,或者已经找到了满足条件的解时,结束搜索。
4. 八皇后问题的回溯求解算法八皇后问题是一种经典的棋盘问题,其目标是在一个8x8的棋盘上放置8个皇后,使得它们互相之间不会攻击。
以下是八皇后问题的回溯求解算法:def solve_n_queens(n):result = []board = [['.' for _ in range(n)] for _ in range(n)]def is_valid(board, row, col):# 检查同一列是否有其他皇后for i in range(row):if board[i][col] == 'Q':return False# 检查左上方是否有其他皇后i, j = row - 1, col - 1while i >= 0 and j >= 0:if board[i][j] == 'Q':return Falsei -= 1j -= 1# 检查右上方是否有其他皇后i, j = row - 1, col + 1while i >= 0 and j < n:if board[i][j] == 'Q':return Falsei -= 1j += 1return Truedef backtrack(board, row):if row == n:result.append([''.join(row) for row in board])returnfor col in range(n):if is_valid(board, row, col):board[row][col] = 'Q'backtrack(board, row + 1)board[row][col] = '.'backtrack(board, 0)return result以上代码中,solve_n_queens函数接受一个整数n作为参数,表示棋盘的大小。
棋盘问题总结
棋盘问题总结我们在研究问题时经常能碰到这⼀类为题:在某个棋盘上有⼀种棋⼦,问最多放下⼏个棋⼦。
或者有⼀堆棋⼦,问你移去最少的棋⼦数⽬,使得剩下来的棋⼦两两不攻击。
先看下⾯这道题问题 E: P1035时间限制: 1 Sec 内存限制: 128 MB提交: 82 解决: 35[][][]题⽬描述给出⼀张n*n(n< =100)的国际象棋棋盘,其中被删除了⼀些点,问可以使⽤多少1*2的多⽶诺⾻牌进⾏掩盖。
输⼊第⼀⾏为n,m(表⽰有m个删除的格⼦)第⼆⾏到m+1⾏为x,y,分别表⽰删除格⼦所在的位置 x为第x⾏ y为第y列输出⼀个数,即最⼤覆盖格数样例输⼊8 0样例输出32这道题先想的是状压DP(爆搜)后来不会做啦。
其实⼀个棋⼦只能和它上下左右4块中的⼀块拼成⼀⼤块,所以我们把每个棋⼦与其上下左右四个棋⼦连⼀条边。
连完所有的边后,我们发现要求的就是最多有多少的边(顶点不能重复)想到了什么?⼆分图匹配。
但它不⼀定是个⼆分图啊。
我们需要证明这⼀点。
⼀种⼝糊的⽅法就是显然⼀个点仅⾛奇数次肯定不能回到原点,所以原图中不存在奇数边的环路,就是⼆分图啦。
还有⼀种⽐较巧妙和通⽤的⽅法就是将棋盘⿊⽩染⾊,所有⿊的只能与⽩点发⽣关系,就是显然的⼆分图了(⿊⽩两个点集)。
对于棋⼦的问题,我们只要在相互冲突的棋⼦连上⼀条边,然后简单的证明⼀下是不是⼆分图,最后求最⼤⼦独⽴集或最⼤匹配即可。
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;#define grey 2#define black 1#define white 0int sum,n,m,Map[105][105],color[105][105],num_white,num_black,White[105],Black[10005],used[10005],match[10005];bool dfs(int u){int t,i;for (int v=1;v<=num_white;v++){i=White[v];if (used[i]==0 && Map[u][i]){used[i]=1;t=match[i];match[i]=u;if (t==0 || dfs(t)) return1;match[i]=t;}}return0;}void make_way(int u,int v){Map[u][v]=1;}int make_num(int a,int b){return ((n)*(a-1)+b);}void make_edge(){for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(color[i][j]!=grey){if(color[i][j]==white){White[++num_white]=make_num(i,j);}else Black[++num_black]=make_num(i,j);if(i>1&&color[i-1][j]!=grey) make_way(make_num(i,j),make_num(i-1,j));if(j>1&&color[i][j-1]!=grey) make_way(make_num(i,j),make_num(i,j-1));if(i<n&&color[i+1][j]!=grey) make_way(make_num(i,j),make_num(i+1,j));if(j<n&&color[i][j+1]!=grey) make_way(make_num(i,j),make_num(i,j+1));}}void draw(int n){for(int i=1;i<=n;i++){if(i%2) color[i][1]=black;else color[i][1]=white;for(int j=2;j<=n;j++){color[i][j]=1^color[i][j-1];}}}void print(){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)cout<<color[i][j];cout<<endl;}}int main(){scanf("%d %d",&n,&m);draw(n);int a,b;for(int i=1;i<=m;i++)scanf("%d %d",&a,&b),color[a][b]=grey;make_edge();//print();for(int i=1;i<=num_black;i++){memset(used,0,sizeof(used));if(dfs(Black[i]))sum++;//cout<<Black[i]<<endl;}cout<<sum<<endl;}#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;#define grey 2#define black 1#define white 0int sum,n,m,Map[105][105],color[105][105],num_white,num_black,White[105],Black[10005],used[10005],match[10005]; bool dfs(int u){int t,i;for (int v=1;v<=num_white;v++){i=White[v];if (used[i]==0 && Map[u][i]){used[i]=1;t=match[i];match[i]=u;if (t==0 || dfs(t)) return1;match[i]=t;}}return0;}void make_way(int u,int v){Map[u][v]=1;}int make_num(int a,int b){return ((n)*(a-1)+b);}void make_edge(){for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(color[i][j]!=grey){if(color[i][j]==white){White[++num_white]=make_num(i,j);}else Black[++num_black]=make_num(i,j);if(i>1&&color[i-1][j]!=grey) make_way(make_num(i,j),make_num(i-1,j));if(j>1&&color[i][j-1]!=grey) make_way(make_num(i,j),make_num(i,j-1));if(i<n&&color[i+1][j]!=grey) make_way(make_num(i,j),make_num(i+1,j));if(j<m&&color[i][j+1]!=grey) make_way(make_num(i,j),make_num(i,j+1)); }}void draw(int n){for(int i=1;i<=n;i++){if(i%2) color[i][1]=black;else color[i][1]=white;for(int j=2;j<=n;j++){color[i][j]=1^color[i][j-1];}}}void print(){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)cout<<color[i][j];cout<<endl;}}int main(){scanf("%d %d",&n,&m);draw(n);int a,b;for(int i=1;i<=m;i++)scanf("%d %d",&a,&b),color[a][b]=grey;make_edge();//print();for(int i=1;i<=num_black;i++){memset(used,0,sizeof(used));if(dfs(Black[i]))sum++;//cout<<Black[i]<<endl;}cout<<sum<<endl;}。
棋盘算法实验报告(3篇)
个人自我介绍简单大方
很抱歉,但我无法为您提供____字的自我介绍。
以下是一个简洁而大方的自我介绍示例,供您参考:
大家好,我叫[姓名]。
很高兴有机会向大家介绍一下自己。
我出生并长大在[所在地],是一个勤奋、积极向上的人。
在学业方面,我于[毕业时间]从[学校名称]获得了[学位/专业]学位。
在大学期间,我通过自我努力和课外学习,取得了良好的学术成绩,并参与了一些学生组织和社团活动。
这些经历不仅培养了我的团队合作和领导能力,也加强了我的沟通和组织能力。
在工作方面,我有[工作年限]年的相关工作经验。
我曾在[公司/组织名称]担任[职位],负责[工作职责]。
在这期间,我不断努力提升自己的专业知识和技能,以适应快速发展的工作环境。
我善于分析问题并找出解决方案,能够有效地与团队合作并承担责任,这些都为我赢得了同事和上级的认可。
除了工作,我也积极参与志愿者活动,希望能为社区和弱势群体做一点贡献。
我相信,通过奉献和关心他人,我们可以建立一个更加和谐和温暖的社会。
在个人生活中,我喜欢阅读、旅行和运动。
阅读扩展了我的视野,旅行让我能够体验不同的文化和风景,而运动则让我保持健康和积极的精神状态。
此外,我也很喜欢与家人和朋友相处,分享彼此的喜怒哀乐。
总的来说,我是一个热情、乐观、有责任心的人。
我相信勤奋和坚持可以取得成功,而真诚和善良可以赢得他人的信任和支持。
我希望能够在您的团队中发挥我的才能,并与大家一同成长和进步。
这就是我简单的自我介绍,谢谢大家!。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
河南理工大学计算机学院算法分析解题报告
棋盘覆盖问题
专业:软件工程.net11-03班
学号:311109070314
姓名:李少伟
1.问题描述:
在一个2^k×2^k (k≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。
显然,特殊方格在棋盘中可能出现的位置有4^k种,因而有4k种不同的棋盘,下图所示是k=2时16种棋盘中的一个。
棋盘覆盖问题(chess cover problem)要求用下图所示的4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
2.解题思路
关键技术: 分治与递归
分治的技巧在于如何划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋盘均包含一个特殊方格(这句话很重要),从而将原问题分解为规模较小的棋盘覆盖问题。
先把原始棋盘划分成4个相等的棋盘,由于棋盘只有一个特殊棋盘,所以这4个子棋盘中只有一个子棋盘包含该特殊棋盘,以便采用递归的方法求解,可以用1一个L型骨牌覆盖这3个较小棋盘的汇合处。
从而将原问题转换为4个较小规模的棋盘覆盖问题。
递归使用这种划分策略,直至将棋盘分割为1*1的子棋盘。
3.解决方案
数据结构设计:
(1)棋盘:可以一个二维数组board[size][size]表示一个棋盘,其中,size = 2^k。
为了在递归处理的过程中使用同一个棋盘,将数组board设置为全局变量
(2)子棋盘:子棋盘由原始棋盘数组board的行下标tr,列下标tc 表示。
(3)特殊方格:用board[dr][dc]表示特殊方格,dr和dc表示该特殊方格的在二维数组board中的下标
(4)L型骨牌:一个(2^k)*(2^k)的棋盘中有一个特殊方格,所以用到L型骨牌的个数为(4^k - 1)/3,将所有L型骨牌从1开始连续编号,同一个骨牌有3个方格组成,这3个方格用同一个编号。
4.源代码
//问题描述:在一个2^k×2^k (k≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。
显然,特殊方格在棋盘中可能出现的位置有4^k种,因而有4k种不同的棋盘,图4.10(a)所示是k=2时16种棋盘中的一个。
棋盘覆盖问题(chess cover problem)要求用下图所示的4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠
覆盖。
//解题思路:分治的技巧在于如何划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋盘均包含一个特殊方格(这句
话很重要),从而将原问题分解为规模较小的棋盘覆盖问题。
先把原始棋盘划分成4个相等的棋盘,由于棋盘只有一个特殊
棋盘,所以这4个子棋盘中只有一个子棋盘包含该特殊棋盘,以便采用递归的方法求解,可以用1一个L型骨牌覆盖这3个
较小棋盘的汇合处。
从而将原问题转换为4个较小规模的棋盘
覆盖问题。
递归使用这种划分策略,直至将棋盘分割为1*1的
子棋盘。
//关键技术:分治与递归
//开发语言:c++
//运行环境:DEV-C++ 5
//开发日期:2014年4月10日
#include <stdio.h>
#include <stdlib.h>
#define N 100
int board[N][N];
int t;
void ChessBoard(int tr, int tc, int dr, int dc, int size)
{
int m,s;
if(size==1) return;
m=++t;
s=size/2;
if(dr<tr+s&&dc<tc+s) chessboard(tr,tc,dr,dc,s);
else
{
board[tr+s-1][tc+s-1]=m;
chessboard(tr,tc,tr+s-1,tc+s-1,s); }
if(dr<tr+s&&dc>tc+s) chessboard(tr,tc,dr,dc,s);
else
{
board[tr+s-1][tc+s]=m;
chessboard(tr,tc,tr+s-1,tc+s,s); }
if(dr>tr+s&&dc<tc+s) chessboard(tr,tc,dr,dc,s);
else
{
board[tr+s][tc+s-1]=m;
chessboard(tr,tc,tr+s,tc+s-1,s);
}
if(dr>tr+s&&dc>tc+s)
chessboard(tr,tc,dr,dc,s);
else
{
board[tr+s][tc+s]=m;
chessboard(tr,tc,tr+s,tc+s,s);
}
}
void print(int n)
{
int i,j;
for(i=0;i<n;i++)
{
for (j=0;j<n;j++)
{
printf("%d ",board[i][j]);
printf("\n");
}
}
}
int main()
{
int tr,tc,dr,dc,size;
tr=0;
tc=0;
pringtf("请输入棋盘的大小");
scanf("%d",&size);
pringtf("请输入特殊方格的行号");
scanf("%d",&dr);
pringtf("请输入特殊方格的列号");
scanf("%d",&dc);
board[dr-1][dc-1]=0;
chessboard(tr,tc,dr-1,dc-1,size);
print(size);
system("pause");
return 0;
}
5.问题回顾
遇到什么问题,怎么克服。