棋盘覆盖问题

棋盘覆盖问题

棋盘覆盖问题

  棋盘覆盖问题在物理世界的应用

  问题描述

  如何证明该问题有解

  算法实现

  算法分析

棋盘覆盖问题在物理世界的应用

  1. 房间铺瓷砖,要绕开某处(前提是他不把瓷砖切了);

  2. 并行激光手术;

  3. 你们想想吧,有想法私信一下我。

 

问题描述

在一个2^k×2^k个方格组成的棋盘中,若有一个方格与其他方格不同,则称该方格为一特殊方格,且称该棋盘为一个特殊棋盘.显然特殊方格在棋盘上出现的位置有4^k种情形.因而对任何k≥0,有4^k种不同的特殊棋盘. 下图中的特殊棋盘是当k=3时16个特殊棋盘中的一个:

棋盘覆盖问题

题目要求在棋盘覆盖问题中,要用下图所示的4种不同形态的L型骨牌覆盖一个给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖.

棋盘覆盖问题

 

 

如何证明该问题有解

用数学归纳法

  1. 当k = 0时(1 × 1的棋盘),及特殊方格,骨牌数为0;

  2. k > 0时

    (1) 将2^k × 2^k的棋盘划分为4个2^(k-1)×2^(k-1)的子棋盘;

    (2) 在递归之前要将原问题转化为4个较小规模的相同子问题;

    (3) 用一个骨牌覆盖这三个棋盘的汇合处;

    (4) 递归使用这种分割直至缩小到1 × 1。

     

算法实现

  1. 棋盘:可以用一个二维数组board[SIZE] [SIZE]表示一个棋盘,其中,size=2^k。为了在递归处理的过程中使用同一个棋盘,将数组board设为全局变量;

  1. 子棋盘:整个棋盘用二维数组board[SIZE] [SIZE]表示,其中的子棋盘由棋盘左上角的下标tr、tc和棋盘大小s表示;

  1. 特殊方格:用board[x] [y]表示特殊方格,x和y是该特殊方格在二维数组board中的下标;

  1. L型骨牌:一个2^k×2^k的棋盘中有一个特殊方格,所以,用到L型骨牌的个数为(4^k-1)/3,将所有L型骨牌从1开始连续编号,用一个全局变量t = 0表示。

#include<iostream>
#include<algorithm>
#include<cmath>
#define SIZE 1024
using namespace std;
unsigned int board[SIZE][SIZE];//棋盘的大小
int ID = 0;
void ChessBoard(int tc, int tr, int x, int y, int size) //棋盘的行列,特殊棋盘的行列,分割的大小
{
   if (size == 1)//设置阈值,当大小是1,也就是一个方块的时候直接退出,因为不能再切了
       return;
   int s = size / 2;// 二分了,大小是原来的一半,棋盘上表现为被切成了大小相同的四分部
   int id = ++ID; //当前棋盘需要覆盖的id号
   //*************特殊方块在左上角
   if (x < tc+s && y < tr+s){ //在
       ChessBoard(tc, tr, x, y, s);//注意size减半了
  }
   else{//右下角标记id号
       board[tc+s-1][tr+s-1]=id;
       ChessBoard (tc, tr, tc+s-1, tr+s-1, s);
  }

   //************特殊方块在右上角
   if (x >= tc+s && y < tr+s){//在
       ChessBoard(tc+s, tr, x, y, s);//注意size减半了
  }
   else{//左下角标记id号
       board[tc+s][tr+s-1]=id;
       ChessBoard (tc+s, tr, tc+s, tr+s-1, s);
  }
   //************特殊方块在左下角

   if (x < tc+s && y >= tr+s){//在
       ChessBoard(tc, tr+s, x, y, s);//注意size减半了
  }
   else{//右下角标记id号
       board[tc+s-1][tr+s]=id;
       ChessBoard (tc, tr+s, tc+s-1, tr+s, s);
  }

   //************特殊方块在右下角
   if (x >= tc+s && y >= tr+s){//在
       ChessBoard(tc+s, tr+s, x, y, s);//注意size减半了
  }
   else{
       board[tc+s][tr+s]=id;
       ChessBoard (tc+s, tr+s, tc+s, tr+s, s);
  }

}
int main(){
   int k, dr, dc, x, y, size;
   cin >> k >> x >> y;
   size = pow(2, k);
   ChessBoard(0, 0, x, y, size);
   cout<<ID<<endl;
   for(int i=0;i<size;i++){
       for(int j=0;j<size;j++){
           cout<<board[j][i]<<" ";
      }
       cout<<endl;
  }
   return 0;
}



 

算法分析

T(k)满足如下递推式:

  1. 当k = 0时,T(k) = 1

  1. 当k > 0时,T(k) = 4T(k-1)

解此递推式可得T(k) = O(4^k)

 

上一篇:二阶段提交的创新者,阿里私生子seata的公子做派,进来了解一下?(一)


下一篇:STM32_CUBMX串口中断