• 分治与递归-棋盘覆盖问题


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

    图(1)

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

    容易忽视的地方:棋盘分割以后,坐标会发生改变,所以要记录棋盘左上角的方格坐标以推得其他信息

    注意的地方    :递归函数单次完成的任务:判断表格的左上角是不是特殊坐标 ,是则继续递归,不是,则覆盖表格的左上角的右下角,然后递归

                                                                 判断表格的右上角是不是特殊坐标 ,是则继续递归,不是,则覆盖表格的右上角的左下角,然后递归

                                                                 判断表格的左下角是不是特殊坐标 ,是则继续递归,不是,则覆盖表格的左下角的右上角,然后递归

                                                                 判断表格的右下角是不是特殊坐标 ,是则继续递归,不是,则覆盖表格的左上角的左上角,然后递归

                                                                 (递归的意思是 选定好初始值,然后继续执行这个函数,在单次完成时,不用关心)

    所以递归函数有两个部分:一个部分是单次函数功能实现的部分(是特殊位置,不处理,不是特殊位置,为特定的点赋值)

                                          一个是上一个函数递推到下一个函数的部分( 继续递归)

    所以说,继续递归出现的位置非常重要。

    什么时候 继续递归?  分治的时候,分割的时候,由大问题过渡到小问题的时候,(比如找到特殊位置的时候,这时候我们已经做完了对大表的操作,接下来的操作是分割棋盘,所以继续递归)

                            判断该递归是不是符合要求,就看它能不能解决第一次的分治,由于分治的小问题与大问题解法相同,所以接下来递归只要保证初始值不出错。

     //棋盘覆盖问题  
    /* 
    (tr,tc)是棋盘左上角的方格坐标 
    (dr,dc)是特殊方格所在的坐标 
    size是棋盘的行数和列数  
    */   
    #include<iostream>  
    using namespace std;  
    int board[1025][1025];  
    static int tile = 1;  
      
    void ChessBoard(int tr,int tc,int dr,int dc,int size)  
    {  
        if(size==1) return ;//递归边界   
          
        int t=tile++;//L型骨牌号,t是骨牌的值,一个值代表一个骨牌
        int s=size/2;//分割棋盘,s是分割后1/4正方形的边长   
        //覆盖左上角子棋盘   
        if(dr<tr+s && dc<tc+s)  //判断坐标的通式
            ChessBoard(tr,tc,dr,dc,s);//特殊方格在此棋盘中   
        else //此棋盘中无特殊方格,用t号L型骨牌覆盖右下角   
        {  
            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号L型骨牌覆盖左下角   
        {  
            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号L型骨牌覆盖右上角   
        {  
            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号L型骨牌覆盖左上角   
        {  
            board[tr+s][tc+s]=t;  
            //覆盖其余方格   
            ChessBoard(tr+s,tc+s,tr+s,tc+s,s);  
        }  
    }  
      
    int main()  
    {  
        int i,j;  
        int k;  
        while(cin>>k)  
        {  
            int size = 1<<k;  
            int x,y;    
            cin>>x>>y;    
            board[x][y]=0;  
            ChessBoard(0, 0, x, y, size);  
            for(i=0; i<size; i++)  
            {  
                for(j = 0; j < size; j++)  
                   cout<< board[i][j]<<"	";  
                cout<<"
    ";  
            }  
        }  
        return 0;  
    }  
    1.  //棋盘覆盖问题  
    2. /* 
    3. (tr,tc)是棋盘左上角的方格坐标 
    4. (dr,dc)是特殊方格所在的坐标 
    5. size是棋盘的行数和列数  
    6. */   
  • 相关阅读:
    Linux和Windows下获得当前时间并格式化
    CMAKE修改VS总结
    【分享】今日头条测试开发工程师面试题
    httprunner测试框架
    [免费]淘宝性能测试白皮书/淘宝测试架构白皮书/淘宝接口测试白皮书/淘宝探索测试白皮书下载
    雪花算法实验
    使用C#实现SSLSocket加密通讯
    Taurus.MVC 2.3.4 :WebAPI 文档集成测试功能升级:WebAPI批量自动化测试功能。
    SpringBoot的配置详解application
    IDEA找回Run Dashboard
  • 原文地址:https://www.cnblogs.com/wshyj/p/6339871.html
Copyright © 2020-2023  润新知