棋盘覆盖问题

来源:互联网 发布:最陡下降算法 编辑:程序博客网 时间:2024/06/07 09:46

实验目的:熟悉掌握分治算法设计技术

棋盘大小:16*16

基本思想、原理和算法描述:

算法描述:

当k>0时,可以将2^k *2^k棋盘分割为4个2^k-1 * 2^k-1子棋盘。由棋盘覆盖问题得知,特殊方格必位于4个较小的子棋盘中,其余3个子棋盘中无特殊方格。为了将3个无特殊方格的子棋盘转化为特殊棋盘可以将一个L型骨牌覆盖这3个较小棋盘的会合处,所以,这3个子棋盘上被L型覆盖的方格就成为给棋盘上的特殊方格,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归的使用这种分割,直至棋盘简化为1*1棋盘为止。

棋盘:用一个二维数组board[size][size]表示一个棋盘。

子棋盘:子棋盘由棋盘左上角的下标 tr(棋盘上左上角方格的行号)、tc(棋盘上左上角方格的列号)。

特殊方格:用board[dr][dc]表示特殊方格,dr(行号)和dc(列号)是该特殊方格在二维数组board中的下标。

L型骨牌:一个2^k *2^k的棋盘中有一个特殊方格,所以,用到L型骨牌的个数为(4k-1)/3,将所有L型骨牌从1开始连续编号,用一个全局变量tile表示。

                   

程序和结果:

程序:

#include <stdio.h>

#include <math.h>

int tile=1; //记录骨牌的型号

int board[100][100]={0}; //存储棋盘被覆盖的情况

void ChessBoard(int tr,int tc,int dr,int dc,int size)

{ //tr和tc是棋盘左上角的下标,dr和dc是特殊方格的下标,size是棋盘的大小

int t=0;

int s;

if (size==1)return;

t=tile++;

s=size/2; //划分棋盘

 

//覆盖左上角棋盘

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);

}

}

int main()

{

int k,x,y;

printf("棋盘的规模k:");

scanf("%d",&k);

    printf("特殊方格的下标x y:");

scanf("%d %d",&x,&y);

ChessBoard(0,0,x,y,pow(2,k));

for(int i=0; i<pow(2,k); i++)

{

        for (int j=0; j<pow(2,k); j++)

        {

               printf("%-4d",board[i][j]);

        }

        printf("\n");

}

return 0;

}

 

运行结果:

 

 


原创粉丝点击