[分治,递归]棋盘覆盖问题
来源:互联网 发布:淘宝关键词权重怎么刷 编辑:程序博客网 时间:2024/06/02 07:29
问题描述
在一个2^k×2^k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
输入:给定k(1<=k<=10),表示棋盘大小为 2^k×2^k ,在给出特殊方格坐标x,y(0<=x,y<=1024)。
输出,一个边长为2^k的方阵,特殊方格编号0,所有骨牌从1开始编号,数据间间隔TAB。
样例输入:2 0 1
样例输出:
2 0 3 3
2 2 1 3
4 1 1 5
4 4 5 5
分析:
该题关键在于如何划分各L型骨牌所在位置区域。我们发现,L型骨牌占三个方格,我们可以把棋盘从中央分为四块,那么这四块子棋盘中仅一块是有特殊方格的,可以用一块骨牌使得其他三块子棋盘均被覆盖。以此为原则,无论这种分法是否最终可解,我们首先保证了每个子棋盘都有一个特殊方格,所以,分治的模型就出来了。
我们可以用递归来完成分治的任务。每次递归divide(zx,zy,si,x,y),(zx,zy)为子棋盘左上角坐标,si为子棋盘大小,因为棋盘总为正方形,所以si为边长,那么前3个参数就确定了子棋盘的位置和大小;(x,y)表示子棋盘中特殊方格的位置,这个位置是由上层递归分配骨牌后决定的。以此为标准。
递归流程为:
①判断边界,若当前棋盘大小为1,则无法再分割,递归结束。
②定子棋盘中心位置。
③判断特殊方格所在位置(左上,右上,左下,或右下)。
④根据特殊方格位置确定所选L型骨牌,原特殊方格和三个L型骨牌的方格分别为四个子棋盘的特殊方格。
⑤依据④中判断,按编号填充棋盘。
⑥4次递归,分别对应四个子棋盘。
代码如下:(代码为本人手打,限于算法理解能力,代码可读性不强)
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>using namespace std;int K,X,Y,row=1;int ch[1030][1030];int now=1;//骨牌编号。void divide(int zx,int zy,int si,int x,int y)//zx,zy为当前棋盘左上角坐标,si为棋盘大小,x,y为已覆盖的棋盘位置。{if(si==1) return;int mx,my,mid;mid=si/2;//分割得新棋盘大小。mx=zx+si/2-1;//中间点。my=zy+si/2-1;/*for(int i=1;i<=row;i++){for(int j=1;j<=row;j++) printf("%d ",ch[i][j]);printf("\n");}cout<<endl;*/if(x>mx&&y>my)//分四种情况讨论,得出已覆盖的点在棋盘中的位置,再判断取哪个{ch[mx][my]=ch[mx+1][my]=ch[mx][my+1]=now;now++;divide(zx,zy,mid,zx+mid-1,zy+mid-1);divide(zx,zy+mid,mid,zx+mid-1,zy+mid);divide(zx+mid,zy,mid,zx+mid,zy+mid-1);divide(zx+mid,zy+mid,mid,x,y);}if(x>mx&&y<=my){ch[mx][my]=ch[mx][my+1]=ch[mx+1][my+1]=now;now++;divide(zx,zy,mid,zx+mid-1,zy+mid-1);divide(zx,zy+mid,mid,zx+mid-1,zy+mid);divide(zx+mid,zy,mid,x,y);divide(zx+mid,zy+mid,mid,zx+mid,zy+mid);} if(x<=mx&&y>my){ch[mx][my]=ch[mx+1][my]=ch[mx+1][my+1]=now;now++;divide(zx,zy,mid,zx+mid-1,zy+mid-1);divide(zx,zy+mid,mid,x,y);divide(zx+mid,zy,mid,zx+mid,zy+mid-1);divide(zx+mid,zy+mid,mid,zx+mid,zy+mid);}if(x<=mx&&y<=my){ch[mx+1][my+1]=ch[mx+1][my]=ch[mx][my+1]=now;now++;divide(zx,zy,mid,x,y);divide(zx,zy+mid,mid,zx+mid-1,zy+mid);divide(zx+mid,zy,mid,zx+mid,zy+mid-1);divide(zx+mid,zy+mid,mid,zx+mid,zy+mid);}}int main(){scanf("%d%d%d",&K,&X,&Y);X++;Y++;ch[X][Y]=0;for(int i=1;i<=K;i++) row*=2;divide(1,1,row,X,Y);for(int i=1;i<=row;i++){for(int j=1;j<=row;j++) printf("%d\t",ch[i][j]);printf("\n");}return 0;}
- 棋盘覆盖问题-递归分治
- [分治,递归]棋盘覆盖问题
- 棋盘覆盖问题(递归与分治)
- [递归与分治]棋盘覆盖问题
- 递归分治解决棋盘覆盖问题
- 递归与分治之棋盘覆盖问题
- 递归与分治中的棋盘覆盖问题
- 分治与递归:棋盘覆盖问题
- 棋盘覆盖(分治-递归)
- 棋盘覆盖(分治、递归)
- 棋盘覆盖问题【分治】
- 分治-棋盘覆盖问题
- 棋盘覆盖问题(分治)
- 棋盘覆盖问题 分治
- 棋盘覆盖【递归分治法】
- 分治递归 棋盘问题
- 递归与分治策略之棋盘覆盖问题
- 棋盘覆盖问题(递归与分治,紫书P229)
- 4.21
- InputStream的read方法读取字节不完全的解决方案
- 原图绘制新图,字符串绘制图片
- ajax跨域访问的两种方式
- java最长上升子序列
- [分治,递归]棋盘覆盖问题
- Spring Boot Validator校验
- 【知识分享】MarkDown编辑器简单使用
- 软考参考书挑错之二
- 编程学习小组
- 决策树学习笔记(一)
- kubernetes 源码分析之ingress(三)
- (三)Mac OS搭建Tomcat服务器 环境配置
- OpenCL、OpenGL和DirectX三者的区别