棋盘覆盖(C语言)

kaizitian 2024-10-26 17:35:01 阅读 96

一、棋盘覆盖-设计规则

       在一个

2^k

×

2^k

个方格组成的棋盘中,恰有一个方格与其他方格不 同,称该方格为“特殊方格”,且称该棋盘为“特殊棋盘”在棋盘覆盖问题中,要用图1所示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格且任何2个L型骨牌不得重叠覆盖

图1


二、棋盘覆盖-设计思路

       棋盘覆盖采用的是分治法,分而治之。当k>0时,将

2^k

×

2^k

棋盘分割为4个

2^{k-1}

×

2^{k-1}

子棋盘,例如图1中4×4的棋盘,将其分割成4个2×2的子棋盘,如2图所示。特殊方格必位于4个较小子棋盘之一中,其余3个子棋盘中无特殊方格。为了 将这3个无特殊方格的子棋盘转化为特殊棋盘,可以用一个L型骨牌覆盖这3 个较小棋盘的会合处,如图3所示,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种分割,直至棋盘简化为棋盘1×1

       

4个较小规模的棋盘问题,4个子问题规模一样,但是处理方式不一样的子问题:

左上角子问题判断特殊方格是否在此棋盘中;如果是在此棋盘,则对此棋盘进行递归调用;如果不在此棋盘,则用t号骨牌覆盖右下角,然后再对此棋盘进行递归调用。

左下角子问题判断特殊方格是否在此棋盘中;如果是在此棋盘,则对此棋盘进行递归调用;如果不在此棋盘,则用t号骨牌覆盖右上角,然后再对此棋盘进行递归调用。

右上角子问题判断特殊方格是否在此棋盘中;如果是在此棋盘,则对此棋盘进行递归调用;如果不在此棋盘,则用t号骨牌覆盖左下角,然后再对此棋盘进行递归调用。

右下角子问题判断特殊方格是否在此棋盘中;如果是在此棋盘,则对此棋盘进行递归调用;如果不在此棋盘,则用t号骨牌覆盖左上角,然后再对此棋盘进行递归调用。


三、棋盘覆盖-设计代码

<code>//C语言

#include <stdio.h>

int Tile = 1; //全局变量骨牌号

int Board[100][100]; //全局数组

//棋盘覆盖

void ChessBoard(int Tr, int Tc, int Dr, int Dc, int Size){

//Tr表示棋盘左上角的行号,Tc表示棋盘左上角的列

//Dr表示棋盘特殊方格的行号,Dc表示棋盘特殊方格的列号

//Size表示棋盘的宽

if(Size == 1)

return;

int t = Tile++; //L型牌骨号

int s = Size/2; //割分棋盘

//覆盖左上角的子棋盘

if(Dr < Tr + s && Dc < Tc + s){

//说明特殊方格在此棋盘中

ChessBoard(Tr,Tc,Dr,Dc,s);

}

else{

//说明特殊方格不在此棋盘中

//需要用t号L型骨牌覆盖右下角

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{

//说明特殊方格不在此棋盘中

//需要用t号L型骨牌覆盖左下角

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{

//说明特殊方格不在此棋盘中

//需要用t号L型骨牌覆盖右上角

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{

//说明特殊方格不在此棋盘中

//需要用t号L型骨牌覆盖左上角

Board[Tr+s][Tc+s] = t;

ChessBoard(Tr+s,Tc+s,Tr+s,Tc+s,s);

}

}

//打印数组

void Func1(int Array[100][100], int Size){

int i,j;

for(i=0;i<Size;i++){

for(j=0;j<Size;j++){

printf("%d\t",Array[i][j]);

}

printf("\n");

}

}

//计算数组的Size:例如k=2,则Size为4,故矩阵为4*4

int Func2(int k){

int sum = 1;

int i;

for(i = 0; i < k; i++){

sum = sum * 2;

}

return sum;

}

int main()

{

int a = 0;

int b = 0;

int k = 0;

int Size = 0;

printf("请输入棋盘大小k(注:大小是2^k*2^k):");

scanf("%d",&k);

printf("输出k=%d:\n",k);

Size = Func2(k);

printf("输出Size=%d:\n",Size);

printf("请输入特殊方格的位置:");

scanf("%d,%d",&a,&b);

Board[a][b] = 0;

ChessBoard(0,0,a,b,Size);

Func1(Board,Size);

return 0;

}

 运行结果


四、棋盘覆盖-时间复杂性分析

T(n) \left\{\begin{matrix} 1 & n=1 \\ 4T(\frac{n}{2})+1 & n>1 \end{matrix}\right.

Master定理方法 :

n^{log_ba}

 

=

  

n^{log_24}

 

=

  

n^2

f(n)

   

=

  

1

 

=

  

n^0

  

\Rightarrow

  

n^{log_ba}

  

>

  

f(n)

\therefore f(n) = O(n^{log_ba-2}) = O(n^{2-2})

\varepsilon =2>0

\because

  根据Master定理规则1:

T(n) = O(n^{log_ba}) = O(n^2)



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。