Incomplete checkerboard covering

本文介绍了一种利用递归方法解决国际象棋板上存在缺失角格的覆盖问题。通过将大棋盘分割为四个小棋盘,并在特定位置放置L形瓷砖来实现覆盖。程序实例演示了如何实现这一过程。

  Cover a checkerboard that has one corner square missing. The size of the board is usuall 2**k, use recursive way the board will be

divided into four 2**(k-1) size small board. Cover the center board with a L shape tile, the one fourth board will the same as the original

board.

 

(r, c) is the left top corner coordinate. s is size / 2.



 

 

tile = 0 # global variable for the L shape tile counting

'''
    brow, bcol is the board's up left corner coordinate
    mrow, mcol is the missing tile's coordinate
    size is the board size
    2**k size board will be divided to four 2**(k-1) size sub-board
    if the missing tile is one fourth board, the L shape will be put
    in the other three one fourth board's center corner
'''
def cover(board, brow, bcol, mrow, mcol, size):
    if size is 1: 
        return
    
    global tile
    tile += 1
    count = tile  # L shape tile number
    s = size // 2  # divide the board
    
    # cover the upper left board
    if mrow < brow + s and mcol < bcol + s:  # if the missing tile is in this square
        cover(board, brow, bcol, mrow, mcol, s)
    else:
        board[brow + s - 1][bcol + s - 1] = count  # cover the down right corner with L shape
        cover(board, brow, bcol, brow + s - 1, bcol + s - 1, s)
    
    # cover the upper right board
    if mrow < brow + s and mcol >= bcol + s:  # if the missing tile is in this square
        cover(board, brow, bcol + s, mrow, mcol, s)
    else:
        board[brow + s - 1][bcol + s] = count  # cover the left down corner with L shape
        cover(board, brow, bcol +s, brow + s - 1, bcol +s, s)
    
    # cover the down left board
    if mrow >= brow + s and mcol < bcol + s:  # if the missing tile is in this square
        cover(board, brow + s, bcol, mrow, mcol, s)
    else:
        board[brow + s][bcol + s - 1] = count  # cover the up right corner with L shape
        cover(board, brow + s, bcol, brow + s, bcol + s - 1, s)
        
    # cover the down right board
    if mrow >= brow + s and mcol >= bcol + s:  # if the missing tile is in this square
        cover(board, brow +s, bcol + s, mrow, mcol, s)
    else:
        board[brow + s][bcol + s] = count  # cover the up left corner with L shape
        cover(board, brow + s, bcol + s, brow + s, bcol + s, s)    
    
def main():
    board = [[0] * 8 for i in range(8)] # 8 * 8 board
    board[7][7] = -1 # the missing corner
    cover(board, 0, 0, 7, 7, len(board))
    
    for row in board:
        print ' %2i' * 8 % tuple(row)
    
if __name__ == '__main__':
    main()
    


 

 

<think>嗯,用户这次问的是C/C++中的不完全类型(incomplete type),结合之前的引用资料和实际编程场景来解答会更有针对性。 用户提到的引用[1]其实点出了关键:不完全类型就是编译器只知道存在这个类型,却不知道它的大小和内部结构。就像只给看包装盒不让拆开看内容。这种设计在数据隐藏和接口封装中特别有用——头文件里只声明个名字,具体实现在源文件里藏起来。 引用[2]提到的Qt报错案例很典型。用户遇到sizeof报错时,编译器其实在说:“QSerialPort::BaudRate这类型我只听过名字,根本不知道它长什么样,怎么算大小?” 这时候用Q_DECLARE_METATYPE声明就是在告诉Qt元系统:“虽然你现在不知道这是啥,但先当它是个合法类型存着”。 需要重点解释的是,不完全类型不是错误而是设计手段。用户可能混淆了“未定义类型”和“不完全类型”的区别——前者是真的缺失定义,后者是故意不给出完整定义。比如经典的前向声明场景: ```cpp class DataContainer; // 前向声明创建不完全类型 void process(DataContainer* dc); // 合法:指针大小固定 // sizeof(DataContainer); // 非法:编译器不知道具体大小 ``` 用户作为开发者可能更关心实际问题,所以特意补充了典型错误场景:除了sizeof报错,访问成员或传值拷贝也会出问题。Qt那个案例里,QVariant需要完整类型是因为它本质是在做内存拷贝,必须知道对象尺寸。 最后用文件操作FILE*的例子收尾,因为这个最贴近系统级编程的实际应用——所有文件操作函数都用指针,具体FILE结构体定义藏在标准库实现里,用户完全不需要关心。 </think> 在C/C++编程中,**不完全类型(incomplete type)** 指编译器已知其存在但尚未获得完整定义的类型。这种类型只能以受限方式使用,常见于以下场景: ### 核心特性 1. **定义缺失** 编译器知道类型名称,但无法确定其内存布局(大小、成员等): ```c struct Data; // 前向声明 → 此时 Data 是不完全类型 ``` 2. **使用限制** - ✅ 允许:**指针/引用**声明(指针大小固定) ```c struct Data* ptr; // 合法 void process(Data& ref); // 函数声明合法 ``` - ❌ 禁止: - 定义对象(需要知道内存大小) ```c Data obj; // 错误:invalid use of incomplete type ``` - 访问成员(需知道结构) ```c ptr->value; // 错误:成员未定义 ``` - 使用 `sizeof`(需计算大小) ```c sizeof(Data); // 错误:invalid application of sizeof ``` ### 典型应用场景 1. **数据隐藏(接口封装)** 头文件仅声明不完全类型,实现在源文件中隐藏: ```c // api.h struct HiddenImpl; // 不完全类型声明 HiddenImpl* create_api(); void use_api(HiddenImpl*); ``` ```c // api.c struct HiddenImpl { // 完整定义仅在实现文件可见 int internal_data; char buffer[256]; }; ``` 2. **解决循环依赖** 当类型相互引用时,通过前向声明打破循环: ```c struct B; // 不完全类型声明 struct A { B* b_ptr; // 允许使用指针 }; struct B { A* a_ptr; }; ``` 3. **库开发中的元编程(如Qt示例)** 当类型未在元系统中注册时,会导致编译错误: ```cpp // 错误:QVariant 无法识别 QSerialPort::BaudRate QVariant v = QSerialPort::Baud115200; // 解决方案:声明为元类型(使类型成为完全类型) Q_DECLARE_METATYPE(QSerialPort::BaudRate); ``` 引用[^2]中的问题正是因为 `QSerialPort::BaudRate` 在相关上下文中被视为不完全类型所致。 ### 与完整类型的关系 | **操作** | 不完全类型 | 完整类型 | |-------------------|------------|----------| | 定义对象 | ❌ | ✅ | | 取 `sizeof` | ❌ | ✅ | | 声明指针/引用 | ✅ | ✅ | | 访问成员 | ❌ | ✅ | ### 经典案例:文件操作 ```c FILE* fp; // FILE 在标准库头文件中通常为不完全类型 fp = fopen("file.txt", "r"); // 用户无需知道 FILE 的具体结构,通过指针操作接口 ``` 此设计隐藏了系统级实现的细节[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值