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

#include<stdio.h>
#include<iostream>
#include<cmath>

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

 

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值