残缺棋盘 分治

在这里插入图片描述
分析:
在这种限制条件下,所需要的三格板总数为?
1)被覆盖板面积(除去残缺方格)为2k×2k-1 (k≥1) ;
2)三格板之间不能重叠;
3)三格板不能覆盖残缺方格,但必须覆盖其他所有方格。

(2k×2k-1)/3

2^k^×2^k^-1--->4^k^-1---->(3+1)^k^-1所得结果一定会被三整除

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<iostream>

using namespace std;

int amount = 0;//用的块数 
int Board[100][100];//棋盘记录 

void Cover(int tr,int tc,int dr,int dc,int size)
{
	int s;
	int t;
	if(size==1) return;
	s=size/2;//拆分成四份小格
	t=++amount; 
	//第一种情况,残缺方块在左上角
	if(dr < tr + s && dc < tc +s)
	{
		Cover(tr,tc,dr,dc,s);//进入残缺方格所在小块的进一步划分 
	}else{
		Board[tr+s-1][tc+s-1] = t;
		Cover(tr,tc,tr+s-1,tc+s-1,s);
	}
	//第二种情况,残缺方块在右上角
	if(dr < tr + s && dc >= tc +s)
	{
		Cover(tr,tc+s,dr,dc,s);//进入残缺方格所在小块的进一步划分 
	}else{
		Board[tr+s-1][tc+s]=t;
		Cover(tr,tc+s,tr+s-1,tc+s,s);
	}
	//第三种情况,残缺方块在左下角
	if(dr >= tr + s && dc < tc +s)
	{
		Cover(tr+s,tc,dr,dc,s);//进入残缺方格所在小块的进一步划分 
	}else{
		Board[tr+s][tc+s-1]=t;
		Cover(tr+s,tc,tr+s-1,tc+s,s);
	}
	//第四种情况,残缺方块在右下角
	if(dr >= tr + s && dc >= tc +s)
	{
		Cover(tr+s,tc+s,dr,dc,s);//进入残缺方格所在小块的进一步划分 
	}else{
		Board[tr+s][tc+s]=t;
		Cover(tr+s,tc+s,tr+s,tc+s,s);
	}
}


int main()
{
    int size,r,c,row,col;//棋盘大小size*size  棋盘左上角顶格的坐标(r,c) 残缺位置(row,col) 
    printf("请输入棋盘大小(2的整数幂)size: "); 
    scanf("%d",&size);
    printf("请输入残缺方块的位置:"); 
    scanf("%d%d",&row,&col);
    Cover(0,0,row,col,size);
    for (r = 0; r < size; r++)
    {
        for (c = 0; c < size; c++)
        {
            printf("%2d ",Board[r][c]);
        }
        printf("\n");
    }

    return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
残缺棋盘问题是一个经典的分治算法问题,可以使用递归的方式来解决。 以下是一份使用C语言实现的代码示例: ```c #include <stdio.h> #include <stdlib.h> #define N 8 int board[N][N]; void chessboard(int tr, int tc, int dr, int dc, int size, int tile) { if (size == 1) { return; } int t = tile++, s = size / 2; // 检查特殊方格是否已经被覆盖 if (dr < tr + s && dc < tc + s) { chessboard(tr, tc, dr, dc, s, t); } else { board[tr + s - 1][tc + s - 1] = t; chessboard(tr, tc, tr + s - 1, tc + s - 1, s, t); } if (dr < tr + s && dc >= tc + s) { chessboard(tr, tc + s, dr, dc, s, t); } else { board[tr + s - 1][tc + s] = t; chessboard(tr, tc + s, tr + s - 1, tc + s, s, t); } if (dr >= tr + s && dc < tc + s) { chessboard(tr + s, tc, dr, dc, s, t); } else { board[tr + s][tc + s - 1] = t; chessboard(tr + s, tc, tr + s, tc + s - 1, s, t); } if (dr >= tr + s && dc >= tc + s) { chessboard(tr + s, tc + s, dr, dc, s, t); } else { board[tr + s][tc + s] = t; chessboard(tr + s, tc + s, tr + s, tc + s, s, t); } } int main() { int i, j, dr, dc; for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { board[i][j] = -1; } } printf("请输入残缺方格的坐标(行列坐标之间用空格分隔):"); scanf("%d %d", &dr, &dc); board[dr][dc] = 0; chessboard(0, 0, dr, dc, N, 1); printf("棋盘如下:\n"); for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { printf("%2d ", board[i][j]); } printf("\n"); } return 0; } ``` 在这个代码示例中,我们定义了一个8x8的二维数组`board`来表示棋盘,-1表示未覆盖的方格,其他数字表示覆盖的方格的编号。我们使用`chessboard`函数来递归地填充棋盘。该函数的参数包括当前棋盘的左上角坐标`(tr, tc)`、残缺方格的坐标`(dr, dc)`、当前棋盘的大小`size`和当前可用的编号`tile`。 在每次递归中,我们首先检查特殊方格是否已经被覆盖。如果特殊方格在当前棋盘的左上角象限内,我们继续递归处理该象限。否则,我们选取一个未被使用的编号`t`来覆盖当前象限的右下角方格,并递归处理其他三个象限。 最后,我们在`main`函数中读取残缺方格的坐标,将其标记为0,然后调用`chessboard`函数来填充整个棋盘。我们打印出填充后的棋盘,即可得到最终的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值