[算法设计与分析]4.3.3二分法不相似情况(残缺棋盘)

#include
#include
#include

using namespace std;

const int N = 100;
int amount = 0;
int board[N][N];

void IncompleteChessBoard();

void Cover(int tr, int tc, int dr, int dc, int sizes);//tr子棋盘左上角方格所在行
                                                        //tc子棋盘左上角方格所在列
                                                        //dr残缺方格行
                                                        //dc残缺方格列
                                                        //sizes棋盘的行数或者列数
void OutputBoard(int board[][N], int sizes);

int main ()
{
    IncompleteChessBoard();
}

void IncompleteChessBoard()
{

    int k = 2;//假设棋盘有2^k*2^k个方格
    int sizes = 1, x, y, i, j;
    sizes = pow(2, k);//棋盘的边长
    x = 1, y = 3;//假定(1,3)位残缺位
    Cover(0, 0, x, y, sizes);
    OutputBoard(board, sizes);
}

void Cover(int tr, int tc, int dr, int dc, int sizes)
{
    int s, t;
    if(sizes < 2)
        return;
    amount++;
    t = amount;//t中存储的是已经填充的拼图数
    
    s = sizes / 2;//s是子棋盘边长的一半

    if(dr < tr + s && dc < tc + s)//证明残缺位置在子棋盘的左上部分
    {
        Cover(tr, tc, dr, dc, s);//此时子棋盘的左上角方格坐标和残缺方格坐标不变 只需要将子棋盘的规模缩小即可

        board[tr + s - 1][tc + s] = t;//这三步操作的目的是将子棋盘的中间位置进行覆盖 避开左上部分 因为已知残缺部分在左上
        board[tr + s][tc + s - 1] = t;
        board[tr + s][tc + s] = t;

        //依次递归覆盖其他三个部分
        Cover(tr, tc + s, tr + s - 1, tc + s, s);//右上部分 此时的残缺位置是刚刚在当前子棋盘中部覆盖的部分
        Cover(tr + s, tc, tr + s, tc + s - 1, s);
        Cover(tr + s, tc + s, tr + s, tc + s, s);
    }
    //下面几部分原理相同 都是讲子棋盘划分四块然后进行递归 并构造新的残缺
    else if(dr < tr + s && dc >= tc + s)
    {
        Cover(tr, tc + s, dr, dc, s);

        board[tr + s - 1][tc + s - 1] = t;
        board[tr + s][tc + s - 1] = t;
        board[tr + s][tc + s] = t;

        Cover(tr, tc, tr + s - 1, tc + s - 1, s);
        Cover(tr + s, tc, tr + s, tc + s - 1, s);
        Cover(tr + s, tc + s, tr + s, tc + s, s);
    }
    else if(dr >= tr + s && dc < tc + s)
    {
        Cover(tr + s, tc , dr, dc, s);

        board[tr + s - 1][tc + s - 1] = t;
        board[tr + s - 1][tc + s] = t;
        board[tr + s][tc + s] = t;

        Cover(tr, tc, tr + s - 1, tc + s - 1, s);
        Cover(tr, tc + s, tr + s - 1, tc + s, s);
        Cover(tr + s, tc + s, tr + s, tc + s, s);
    }
    else if(dr >= tr + s && dc >= tc + s)
    {
        Cover(tr + s, tc + s, dr, dc, s);

        board[tr + s - 1][tc + s - 1] = t;
        board[tr + s - 1][tc + s] = t;
        board[tr + s][tc + s - 1] = t;

        Cover(tr, tc, tr + s - 1, tc + s - 1, s);
        Cover(tr, tc + s, tr + s - 1, tc + s, s);
        Cover(tr + s, tc, tr + s, tc + s - 1, s);
    }
}
void OutputBoard(int board[][N], int sizes)
{
    for(int i = 0; i < sizes; i++)
    {//一次中填充的拼图(3块)有相同的编号
        for(int j = 0; j < sizes; j++)
        {
            cout << board[i][j] << " ";
        }
        cout << endl;
    }
}

 

你可能感兴趣的:(算法设计与分析)