• 2017.12.5 算法分析----棋盘覆盖问题


    棋盘覆盖问题

    如何应用分治法求解棋盘覆盖问题呢?

    分治的技巧在于如何划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋盘均包含一个特殊方格,
    从而将原问题分解为规模较小的棋盘覆盖问题。k>0时,可将2^k×2^k的棋盘划分为4个2^(k-1)×2^(k-1)的子棋盘,
    由于原棋盘只有一个特殊方格,所以,这4个子棋盘中只有一个子棋盘包含该特殊方格,其余3个子棋盘中没有特殊方格。
    为了将这3个没有特殊方格的子棋盘转化为特殊棋盘,以便采用递归方法求解,可以用一个L型骨牌覆盖这3个较小棋盘的会合处,
    从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种划分策略,直至将棋盘分割为1×1的子棋盘。
    

    利用分治的方法

    分治实现的三步骤:

    划分问题:将2k∗2k的棋盘划分为2k−1∗2k−1这样的子棋盘4块。
    递归求解:递归填充各个格子,填充分为四个情况,在下面会有解释,递归出口为k=0也就是子棋盘方格数为1。
    合并问题:不需要合并子问题。
    递归填充的四种情况
    如果黑方块在左上子棋盘,则递归填充左上子棋盘;否则填充左上子棋盘的右下角,将右下角看做黑色方块,然后递归填充左上子棋盘。
    如果黑方块在右上子棋盘,则递归填充右上子棋盘;否则填充右上子棋盘的左下角,将左下角看做黑色方块,然后递归填充右上子棋盘。
    如果黑方块在左下子棋盘,则递归填充左下子棋盘;否则填充左下子棋盘的右上角,将右上角看做黑色方块,然后递归填充左下子棋盘。
    如果黑方块在右下子棋盘,则递归填充右下子棋盘;否则填充右下子棋盘的右下角,将左上角看做黑色方块,然后递归填充右下子棋盘。
    

    所以得出一个算法就是:

    设T(k)是算法ChessBoard覆盖一个2^k×2^k棋盘所需时间,从算法的划分
    策略可知,T(k)满足如下递推式:
    T(k) = 1 当k=0时
    T(k) = 4T(k-1) 当k>0时
    解此递推式可得T(k)=O(4^k)。
    
    

    代码实现:

    #include "stdafx.h"
    #include <iostream>     
    using namespace std; 
    
    int tile = 1;//全局变量 骨牌编号
    int Board[4][4];//棋盘
    void ChessBoard(int tr,int tc,int dr,int dc,int size);
    
    int main()
    {
        for(int i=0; i<4; i++)
        {
            for(int j=0; j<4; j++)
            {
                Board[i][j] = 0;
            }
        }
    
        ChessBoard(0,0,2,3,4);
    
        for(int i=0; i<4; i++)
        {
            for(int j=0; j<4; j++)
            {
                cout<<Board[i][j]<<" ";
            }
            cout<<endl;
        }
    }
    
    /**
     * tr : 棋盘左上角的行号,tc棋盘左上角的列号
     * dr : 特殊方格左上角的行号,dc特殊方格左上角的列号
     * size :size = 2^k 棋盘规格为2^k*2^k
     */
    void ChessBoard(int tr,int tc,int dr,int dc,int size)
    {
        if(size == 1)
        {
            return;
        }
        int t = tile++;//L型骨牌编号
        int s = size/2;//分割棋盘
    
        //覆盖左上角子棋盘
        if(dr<tr+s && dc<tc+s)//特殊方格在此棋盘中
        {
            ChessBoard(tr,tc,dr,dc,s);
        }
        else//特殊方格不在此棋盘中
        {
            //用编号为t的骨牌覆盖右下角
            Board[tr+s-1][tc+s-1] = t;
            //覆盖其余方格
            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//特殊方格不在此棋盘中
        {
            //用编号为t的骨牌覆盖左下角
            Board[tr+s-1][tc+s] = t;
            //覆盖其余方格
            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//特殊方格不在此棋盘中
        {
            //用编号为t的骨牌覆盖右上角
            Board[tr+s][tc+s-1] = t;
            //覆盖其余方格
            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//特殊方格不在此棋盘中
        {
            //用编号为t的骨牌覆盖左上角
            Board[tr+s][tc+s] = t;
            //覆盖其余方格
            ChessBoard(tr+s,tc+s,tr+s,tc+s,s);
        }
    
    }
    
  • 相关阅读:
    .net 关于路径的总结
    asp.net Base64加解密
    asp.net中的<% %>,<%= %>,<%# %><%$ %>的使用
    asp.net Swiper 轮播动画
    ASP.NET中Literal控件的使用方法(用于向网页中动态添加内容)
    asp.net 获取表单中控件的值
    rgb值转换成16进制
    关于background全解
    移动端的性能陷阱
    原生JS实现雪花特效
  • 原文地址:https://www.cnblogs.com/qichunlin/p/7990153.html
Copyright © 2020-2023  润新知