棋盘覆盖问题(分治)
棋盘覆盖问题:
问题描述:
现在有一个大小的棋盘,在棋盘内部有一只特别的棋子,输入的坐标为X和Y。
要求尝试用4种不同类型的骨牌将棋盘覆盖,要求,骨牌之间不得重叠,并且骨牌不得覆盖特殊棋子,每个骨牌占用3个单位大小,形状如下。
棋盘假设如下:
思路分析:
对于这种题目,我们先从k=0开始分析:
当k=0的时候,棋盘大小为1,整个棋盘被特殊棋子覆盖。
当k=1的时候,棋盘大小为4,棋盘可以被一个骨牌外加一个特殊棋子覆盖
假设如下:
当k=2的时候,棋盘大小为16,棋盘可以被这样覆盖
当k=3的时候,棋盘可以被这样覆盖
第一次我写到这里的时候就发现,因为这个棋盘是
假设当我k=2的时候,棋盘大小是16,那么我可以将棋盘平均分成四块,每块大小是4,那么特殊棋子必须落在其中一个区域,这是,只要我让每一个区域的大小从4变成3,我就可以填满整个棋盘,所以可以选择在分界线填充骨牌。如下图:
那么,剩下的区域我都有相应的骨牌填充。
当k=3的时候,我们可以先把64的空间平均分成16*4,我们已经有一个区域有一个特殊棋子了,接下来,我们要把骨牌放在分界线上,让骨牌每一个单位成为新的假设的“特殊棋子”,这时候问题就变成了求4个棋盘大小为16的棋盘覆盖问题了。
以此类推…
实际上,这就是我们算法里面常见的分治算法,将一个问题分成若干个小问题,问题之间相互不影响,通过解决所有子问题实现求出主问题的办法。
代码如下:
- #define _CRT_SECURE_NO_WARNINGS
- #include<iostream>
- #include<cstdlib>
- #include<cstring>
- usingnamespacestd;
- #defineMAX_SIZE100
- intboard[MAX_SIZE][MAX_SIZE]; /*definecheckerboard MAXSIZE = 64*64 */
- inttmp=1;
- intlocate(intdes_x,intdes_y,intlength,intx,inty)//指定棋子(des_x,des_y)的棋盘长度为length,左上角坐标为xy的位置
- {
- /*
- 只要将棋子所在区域标记为1234,用于判断与其他棋子的区域是否相同
- */
- if(des_x<length+x&&des_y<length+y)
- return1;
- if(des_x<length+x&&des_y>=length+y)
- return2;
- if(des_x>=length+x&&des_y<length+y)
- return3;
- if(des_x>=length+x&&des_y>=length+y)
- return4;
- return0;
- }
- voidcheckboard(intlength,intx,inty)//棋盘长度为length,棋盘最左上角的坐标为xy
- {
- if(length==2)
- {
- for(inti=x;i<x+length;i++)
- for(intj=y;j<y+length;j++)
- if(board[i][j]==-1)//是空,则直接覆盖
- board[i][j]=tmp;
- tmp++;
- }
- else
- {
- inti,j;
- intdir_x,dir_y;
- for(i=x;i<x+length;i++)
- for(j=y;j<y+length;j++)
- {
- if(board[i][j]!=-1)//找到非空棋子
- {
- dir_x=i;
- dir_y=j;
- }
- }
- length/=2;//下一次循环棋盘长度缩小为二分之一
- intmode=locate(dir_x,dir_y,length,x,y);//定位特殊棋子位置,此时(length+x,length+y)是中线
- for(i=x+length-1;i<=x+length;i++)//遍历分界线的四个棋子
- for(j=y+length-1;j<=x+length;j++)
- {
- if(locate(i,j,length,x,y)!=mode)//只要和特殊棋子不在同一区域就覆盖
- board[i][j]=tmp;
- }
- tmp++;
- checkboard(length,x,y);
- checkboard(length,x,y+length);
- checkboard(length,x+length,y);
- checkboard(length,x+length,y+length);
- }
- }
- intmain(void)
- {
- intsize,x,y,len;
- memset(board,-1,sizeof(board));
- cout<<"请输入棋盘大小的K值:"<<endl;
- cin>>len;
- size=(int)pow(2,len);
- cout<<"size = "<<size<<endl;
- cout<<"请输入特殊棋子的行坐标X(从0开始计算):";
- cin>>x;
- cout<<"请输入特殊棋子的列坐标y(从0开始计算):";
- cin>>y;
- board[x][y]=0;
- cout<<"x = "<<x<<" y = "<<y<<endl;
- checkboard(size,0,0);
- for(inti=0;i<size;i++)
- {
- for(intj=0;j<size;j++)
- {
- cout<<board[i][j]<<"\t";
- }
- cout<<endl;
- }
- cout<<endl;
- system("pause");
- return0;
- }
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdlib>
#include<cstring>
usingnamespacestd;
#defineMAX_SIZE100
intboard[MAX_SIZE][MAX_SIZE]; /*definecheckerboard MAXSIZE = 64*64 */
inttmp=1;intlocate(intdes_x,intdes_y,intlength,intx,inty)//指定棋子(des_x,des_y)的棋盘长度为length,左上角坐标为xy的位置
{/*只要将棋子所在区域标记为1234,用于判断与其他棋子的区域是否相同*/if(des_x<length+x&&des_y<length+y)return1;if(des_x<length+x&&des_y>=length+y)return2;if(des_x>=length+x&&des_y<length+y)return3;if(des_x>=length+x&&des_y>=length+y)return4;return0;
}voidcheckboard(intlength,intx,inty)//棋盘长度为length,棋盘最左上角的坐标为xy
{if(length==2){for(inti=x;i<x+length;i++)for(intj=y;j<y+length;j++)if(board[i][j]==-1)//是空,则直接覆盖board[i][j]=tmp;tmp++;}else{inti,j;intdir_x,dir_y;for(i=x;i<x+length;i++)for(j=y;j<y+length;j++){if(board[i][j]!=-1)//找到非空棋子{dir_x=i;dir_y=j;}}length/=2;//下一次循环棋盘长度缩小为二分之一intmode=locate(dir_x,dir_y,length,x,y);//定位特殊棋子位置,此时(length+x,length+y)是中线for(i=x+length-1;i<=x+length;i++)//遍历分界线的四个棋子for(j=y+length-1;j<=x+length;j++){if(locate(i,j,length,x,y)!=mode)//只要和特殊棋子不在同一区域就覆盖board[i][j]=tmp;}tmp++;checkboard(length,x,y);checkboard(length,x,y+length);checkboard(length,x+length,y);checkboard(length,x+length,y+length);}
}
intmain(void)
{intsize,x,y,len;memset(board,-1,sizeof(board));cout<<"请输入棋盘大小的K值:"<<endl;cin>>len;size=(int)pow(2,len);cout<<"size = "<<size<<endl;cout<<"请输入特殊棋子的行坐标X(从0开始计算):";cin>>x;cout<<"请输入特殊棋子的列坐标y(从0开始计算):";cin>>y;board[x][y]=0;cout<<"x = "<<x<<" y = "<<y<<endl;checkboard(size,0,0);for(inti=0;i<size;i++){for(intj=0;j<size;j++){cout<<board[i][j]<<"\t";}cout<<endl;}cout<<endl;system("pause");return0;
}
棋盘覆盖问题(分治)相关推荐
- 棋盘覆盖问题--分治策略
问题描述: 在一个2k×2k (k≥0,k为上标)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格.棋盘覆盖问题要求用图(b)所示的4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外 ...
- 棋盘覆盖(分治典例)
问题描述 在一个2^k×2^k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘.在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特 ...
- 递归与分治之棋盘覆盖问题
在一个2^k * 2^k个方格组成的棋盘中,若有一个方格与其他方格不同,则称该方格为一特殊方格,且称该棋盘为一个特殊棋盘. 显然特殊方格在棋盘上出现的位置有4^k种情形.因而对任何k≥0,有4^k种不 ...
- 计算机基础算法棋盘覆盖,分治算法求解棋盘覆盖问题互动教学过程.doc
分治算法求解棋盘覆盖问题互动教学过程 分治算法求解棋盘覆盖问题互动教学过程 摘要:针对算法设计与分析课程难度较大.对学生编程能力要求较高的现状,通过对棋盘覆盖问题的分治算法求解过程进行互动教学设计,引 ...
- 算法笔记 分治:循环赛日程 棋盘覆盖 选择问题 输油管问题 整数因子分解
一.循环赛日程 #include <iostream> #include <vector> #include <string> #include <algor ...
- 算法系列(一):分治策略--棋盘覆盖
算法系列(一):分治策略--棋盘覆盖 一.分析 问题描述: 图1-1 k=2时的一个特殊棋盘 在一个 2^k * 2^k 个方格组成的棋盘中,若恰有一个方格与其它方格不同,则称该方格为一特殊方格,且 ...
- 分治策略------棋盘覆盖(ChessBoard)
棋盘覆盖原理 棋盘覆盖运用的是分治策略. 1.分治的技巧在于如何划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋盘均包含一个特殊方格,从而将原问题分解为规模较小的棋盘覆盖问题. 2.k>0时, ...
- [分治] AOAPC2-ch8 棋盘覆盖问题
题目 棋盘覆盖问题. 有一个2k∗2k2k∗2k2^{k}∗2^{k}的方格棋盘,恰有一个方格是黑色的,其他为白色.你的任务是用包含3个方格的L型牌覆盖所有白色方格.黑色方格不能被覆盖,且任意一个白色 ...
- 棋盘覆盖问题 java_Java基于分治算法实现的棋盘覆盖问题示例
本文实例讲述了Java基于分治算法实现的棋盘覆盖问题.分享给大家供大家参考,具体如下: 在一个2^k * 2^k个方格组成的棋盘中,有一个方格与其它的不同,若使用以下四种L型骨牌覆盖除这个特殊方格的其 ...
最新文章
- form的enctype和action
- 数字电子技术基础第三版杨志忠_阎石《数字电子技术基础》(第6版)笔记和课后习题(含考研真题)详解复习笔记资料...
- java多线程编程(一基础概念)
- ping源码分析(超详细,多图,带背景分析)
- 戴尔服务器重装系统蓝屏重启,戴尔电脑装系统蓝屏如何解决?
- Python词频统计与杨辉三角
- 电脑鼠标点一下就选很多程序
- winmerge对比时出现中文乱码的解决办法
- 阿里巴巴开源力作(二)--分布式流量卫兵Sentinel简介及控制台安装
- 2022中国眼博会,中国北京国际儿童青少年眼睛健康产业展览会
- 神通数据库connect by用法
- 详解EBS接口开发之销售订单挑库发放
- NET MVC5第三方验证——FluentValidation
- C语言学习宝典下载,C语言学习宝典
- python只读打开文件_关于python:只读文件的第一行?
- 装机员U盘安装Win10系统
- 靠收破烂年入60万的思维操作?究竟该怎么做呢?
- 金融项目学习——尚融宝
- 母牛生母牛,母牛生小牛。。。
- PowerBuilder 软件加密实验