算法07:棋盘覆盖——分治法Part3

(3)棋盘覆盖

在一个2k×2k 个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。



分治法的思想:当k>0时,将2k×2k棋盘分割为4个2k-1×2k-1 子棋盘。特殊方格必位于4个较小子棋盘之一中,其余3个子棋盘中无特殊方格。为了将这3个无特殊方格的子棋盘转化为特殊棋盘,可以用一个L型骨牌覆盖这3个较小棋盘的会合处,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种分割,直至棋盘简化为棋盘1×1。 



具体算法:

(1)将棋盘分为4部分,检查特殊方格是否在左上部分

          a.在,继续将左上部分分割;

          b.不在,将这部分右下角的格子填充,作为特殊方格,继续分割;

(2)将左下角、右上角、右下角按同样的方式处理

(3)递归棋盘为1*1时结束


完整算法

#include <cstdlib>
#include <iostream>

using namespace std;

int board[100][100];
int t0 = 0;

void chess_board(int dx, int dy, int tx, int ty, int size )
{
      if(size == 1) return;
      
      int t = ++t0;
      
      int s = size/2;
      
      //检查特殊格是否在左上部分
      if(tx < dx+s && ty < dy+s) {
           chess_board(dx, dy, tx, ty, s); 
      }
      else{//不在右下角填充 
            board[dx+s-1][dy+s-1] = t;
            chess_board(dx, dy, dx+s-1, dy+s-1, s);
      }
      //检查特殊格是否在左下部分
      if(tx >= dx+s && ty < dy+s) {
           chess_board(dx+s, dy, tx, ty, s); 
      }
      else{//不在右上角填充 
            board[dx+s][dy+s-1] = t;
            chess_board(dx+s, dy, dx+s, dy+s-1, s);
      }
      //检查特殊格是否在右上部分
      if(tx < dx+s && ty >= dy+s) {
           chess_board(dx, dy+s, tx, ty, s); 
      }
      else{//不在左下角填充 
            board[dx+s-1][dy+s] = t;
            chess_board(dx, dy+s, dx+s-1, dy+s, s);
      }
      //检查特殊格是否在右下部分 
      if(tx >= dx+s && ty >= dy+s) {
           chess_board(dx+s, dy+s, tx, ty, s) ;
      }
      else{//不在左上角填充 
            board[dx+s][dy+s] = t;
            chess_board(dx+s, dy+s, dx+s, dy+s, s);
      }            
}

int main()
{
    int size, x, y;
    
    while(cin>>size>>x>>y){
    
         chess_board(0, 0, x, y, size);
    
         for(int i = 0; i < size; i++){
               for(int j = 0; j < size; j++){
                    cout<<board[i][j]<<" ";
               }
               cout<<endl;
         }
    }
    
    system("PAUSE");
    return 0;
}

运行结果:


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
L组件填图问题 1.问题描述 设B是一个n×n棋盘,n=2k,(k=1,2,3,…)。用分治法设计一个算法,使得:用若干个L条块可以覆盖住B的除一个特殊方格外的所有方格。其中,一个L条块可以覆盖3个方格。且任意两个L条块不能重叠覆盖棋盘。 例如:如果n=2,则存在4个方格,其中,除一个方格外,其余3个方格可被一L条块覆盖;当n=4时,则存在16个方格,其中,除一个方格外,其余15个方格被5个L条块覆盖。 2. 具体要求 输入一个正整数n,表示棋盘的大小是n*n的。输出一个被L条块覆盖的n*n棋盘。该棋盘除一个方格外,其余各方格都被L条块覆盖住。为区别出各个方格是被哪个L条块所覆盖,每个L条块用不同的数字或颜色、标记表示。 3. 测试数据(仅作为参考) 输入:8 输出:A 2 3 3 7 7 8 8 2 2 1 3 7 6 6 8 4 1 1 5 9 9 6 10 4 4 5 5 0 9 10 10 12 12 13 0 0 17 18 18 12 11 13 13 17 17 16 18 14 11 11 15 19 16 16 20 14 14 15 15 19 19 20 20 4. 设计与实现的提示 对2k×2k的棋盘可以划分成若干块,每块棋盘是原棋盘的子棋盘或者可以转化成原棋盘的子棋盘。 注意:特殊方格位置是任意的。而且,L条块是可以旋转放置的。 为了区分出棋盘上的方格被不同的L条块所覆盖,每个L条块可以用不同的数字、颜色等来标记区分。 5. 扩展内容 可以采用可视化界面来表示各L条块,显示其覆盖棋盘的情况。 经典的递归问题, 这是我的大代码, 只是本人很懒, 不想再优化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值