棋盘覆盖问题(C实现)——分治算法的思想

算法思想参考
https://www.cnblogs.com/Jason-Damon/archive/2013/06/14/3136893.html
https://wenku.baidu.com/view/e331f06c336c1eb91a375d75.html

C语言代码实现

#include<stdio.h>

int matrix[100][100]={0};
int t=0;

void chessboard(int tr,int tc,int dr,int dc,int size);

int main(){
    int size;
    int tr=0,tc=0,dr,dc;
    int i,j;
    scanf("%d",&size);
    scanf("%d %d",&dr,&dc);
    chessboard(0,0,dr,dc,size);
    for(i=0;i<size;i++){
        for(j=0;j<size;j++){
            printf("%2d ",matrix[i][j]);
        }
        printf("\n");
    }
    return 0;
}

void chessboard(int tr,int tc,int dr,int dc,int size){
    if(size==1)return;
    int s=size/2;
    int cnt;
    cnt=t+1;
    t++;    
    //特殊方格在左上部分 
    if(dr<tr+s&&dc<tc+s){
        chessboard(tr,tc,dr,dc,s);
    }
    else {
        matrix[tr+s-1][tc+s-1]=cnt;
        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 {
        matrix[tr+s-1][tc+s]=cnt;
        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 {
        matrix[tr+s][tc+s-1]=cnt;
        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 {
        matrix[tr+s][tc+s]=cnt;
        chessboard(tr+s,tc+s,tr+s,tc+s,s);
    } 
}
  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
棋盘覆盖问题是指在一个2^n * 2^n的棋盘中刚好有一个方格被去掉,我们需要用L型骨牌覆盖所有剩下的方格,每个L型骨牌覆盖三个方格,且不能重叠覆盖。下面是一种基于分治思想算法: 1. 对于当前的棋盘,选取一个未覆盖的方格作为特殊方格,将整个棋盘分成四个子棋盘,每个子棋盘都不包含特殊方格。 2. 对于每个子棋盘,如果子棋盘大小为1*1,则不需要覆盖;否则,对子棋盘递归调用本算法。 3. 在特殊方格所在的子棋盘中,放置一个L型骨牌,覆盖除特殊方格外的另外三个方格。 4. 递归地处理每个子棋盘。 下面是用 C 语言实现代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 定义棋盘大小 #define BOARD_SIZE (1 << 6) // 定义L型骨牌编号 #define TILE_UP_LEFT 0 #define TILE_UP_RIGHT 1 #define TILE_DOWN_LEFT 2 #define TILE_DOWN_RIGHT 3 // 定义L型骨牌的形状 const int tile_shape[4][3][2] = { {{0, 0}, {0, 1}, {1, 0}}, // 上左 {{0, 0}, {0, 1}, {1, 1}}, // 上右 {{0, 0}, {1, 0}, {1, 1}}, // 下左 {{0, 1}, {1, 0}, {1, 1}} // 下右 }; // 棋盘 int board[BOARD_SIZE][BOARD_SIZE]; // 特殊方格坐标 int special_x, special_y; // L型骨牌个数 int tile_count = 0; // 将棋盘打印出来 void print_board() { for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (i == special_x && j == special_y) { printf("X "); } else if (board[i][j] == -1) { printf("# "); } else { printf("%d ", board[i][j]); } } printf("\n"); } printf("\n"); } // L型骨牌覆盖 void tile_cover(int x, int y, int size, int tile_type) { // L型骨牌个数加1 tile_count++; // 如果棋盘大小为1*1,则不需要覆盖 if (size == 1) { return; } // 计算子棋盘大小 int sub_size = size / 2; // 在特殊方格所在的子棋盘中放置L型骨牌 int sub_x = x + sub_size - 1; int sub_y = y + sub_size - 1; int tile_x, tile_y; for (int i = 0; i < 3; i++) { tile_x = sub_x + tile_shape[tile_type][i][0] * sub_size; tile_y = sub_y + tile_shape[tile_type][i][1] * sub_size; board[tile_x][tile_y] = tile_count; } // 在其他三个子棋盘中分别递归调用本函数 tile_cover(x, y, sub_size, TILE_UP_LEFT); tile_cover(x, y + sub_size, sub_size, TILE_UP_RIGHT); tile_cover(x + sub_size, y, sub_size, TILE_DOWN_LEFT); tile_cover(x + sub_size, y + sub_size, sub_size, TILE_DOWN_RIGHT); } int main() { // 初始化棋盘 memset(board, -1, sizeof(board)); // 读入特殊方格坐标 scanf("%d%d", &special_x, &special_y); // 在特殊方格处放置一个0 board[special_x][special_y] = 0; // L型骨牌覆盖 tile_cover(0, 0, BOARD_SIZE, TILE_UP_LEFT); // 打印棋盘 print_board(); return 0; } ``` 在该算法中,我们首先定义了L型骨牌的形状和编号,然后使用递归的方式来覆盖棋盘。在递归过程中,我们选取一个未覆盖的方格作为特殊方格,将整个棋盘分成四个子棋盘,每个子棋盘都不包含特殊方格。在特殊方格所在的子棋盘中,放置一个L型骨牌,覆盖除特殊方格外的另外三个方格,并递归地处理每个子棋盘。最终,我们得到了L型骨牌覆盖后的棋盘。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值