棋盘覆盖问题

来源:互联网 发布:什么直播软件最好 编辑:程序博客网 时间:2024/06/01 09:09
在一个2^k×2^k (k≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。显然,特殊方格在棋盘中可能出现的位置有4^k种,因而有4^k种不同的棋盘,图4.10(a)所示是k=2时16种棋盘中的一个。棋盘覆盖问题(chess cover problem)要求用图4.10(b)所示的4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

解法思路:我们将一个完整的棋盘分解成4个2^(k-1)×2^(k-1)的小的棋盘,那么必然有一个含有这个原始的阴影部分,其他的三个小棋盘必然不含有。
而这些不含有阴影部分的棋盘,其交界处必然可以使用这四种不同的L型骨牌中的一个来覆盖,那么我们使用满足条件的这个骨牌来覆盖的时候,这三个小的棋盘又必然变成了这个大问题的三个小问题。这样我们就会自然想到使用分治法解决。当棋盘的大小为2的时候自然可以直接覆盖。
PS:关于这个问题为什么总是有解,其实很简单。如果对于n=k的规模是有解,那么我们使用分治法来处理n=k+1的时候可以看成处理4个小的n'=k时的结果的综合。又n=2时有解,则可以使用类似数学归纳法的方法证明此问题总是有解。
#include<iostream>#include<iomanip>using namespace std;#define M 10000int map[M][M];int bad;void fill(int stx,int sty,int size,int x,int y){int i,j;if(size==2){bad=bad+1;for(i=stx;i<=stx+size-1;i++)for(j=sty;j<=sty+size-1;j++)if(map[i][j]==-1)map[i][j]=bad;return ;}size=size/2;bad=bad+1;int temp=bad;//尤其注意此局部变量的使用,每次调用fill函数就意味着用一个新的L型板子,bad可以区分各个板子//如果不适用一个局部变量,fill过程类似深搜每搜索一次bad+1,那么对同一块板子其他格子赋值出错if(x<=stx+size-1&&y<=sty+size-1)fill(stx,sty,size,x,y);else {map[stx+size-1][sty+size-1]=temp;fill(stx,sty,size,stx+size-1,sty+size-1);}if(x<=stx+size-1&&y>=sty+size)fill(stx,sty+size,size,x,y);else {map[stx+size-1][sty+size]=temp;fill(stx,sty+size,size,stx+size-1,sty+size);}if(x>=stx+size&&y<=sty+size-1)fill(stx+size,sty,size,x,y);else {map[stx+size][sty+size-1]=temp;fill(stx+size,sty,size,stx+size,sty+size-1);}if(x>=stx+size&&y>=sty+size)fill(stx+size,sty+size,size,x,y);else {map[stx+size][sty+size]=temp;fill(stx+size,sty+size,size,stx+size,sty+size);}}int main(){int n,len,x,y,i,j;cin>>n;while(n--){cin>>len>>x>>y;bad=0;for(i=1;i<=len;i++)for(j=1;j<=len;j++)map[i][j]=-1;map[x][y]=0;fill(1,1,len,x,y);for(i=1;i<=len;i++){for(j=1;j<=len;j++)cout<<setw(3)<<map[i][j];cout<<endl;}}return 0;}




0 0
原创粉丝点击