• 分治算法-残缺棋盘


     残缺棋盘是一个2^k*2^个方格的棋盘,其中恰有1个方格残缺。图中给出,其中残缺部分用阴影表示。


    这样的棋盘称为"三格板",残缺棋盘问题就是用这四种三格板覆盖更大的残缺棋盘。再次覆盖中要求:

    (1)两个三格板不能重复。

    (2)三格板不能覆盖残缺棋盘方格,但必须覆盖到其他所有的方格。

    算法思路:

    利用分治算法将棋盘细化,逐步解决,以4*4为例


    首先判断残缺的位置在哪里,然后在中间填上对应的三格板,如在上图中间拼上三角板(4),变成下面这样


    然后通过中间将其分成了4个2*2的小残缺棋盘,从而问题得以解决


    4*4的分析过于简单,现在我们以8*8为例进行分析,能更清楚的理解这个例子中分治算法的思想


    首先将三格板放置在中间,将其分4个小的4*4的残缺棋盘


    通过红色线将其划分成4个4*4的残缺棋盘,现在以左上的残缺棋盘为例

    然后将左的4*4的小棋盘右划分成了4个2*2的小棋盘,这样就将问题优化成了2*2的三角棋盘的小问题,这样很快就能将左上的4*4的残缺棋盘解决了

    下面继续分析右上的4*4的棋盘,根据残缺的方格在小棋盘中的位置,在中间选择合适的三格板将小的残缺棋盘继续划分,将问题分化成更小的状态


    接着的问题和上面一样分析。右上角的小棋盘很快也能解决了,下面两块残缺棋盘的分析方法和上面的一样,整个问题就这样一步步的分解成小问题,然后解决了。

    下面是源代码

    #include <iostream>
    
    using namespace std;
    
    int amount,Board[100][100];
    
    void Cover(int tr,int tc,int dr,int dc,int size)
    {
        int s,t;
        if(size<2)
            return ;
        amount++;
        t=amount;
        s=size/2;
        if(dr<tr+s&&dc<tc+s)//残缺在左上角
        {
            //覆盖中间位置
            Board[tr+s-1][tc+s]=t;
            Board[tr+s][tc+s-1]=t;
            Board[tr+s][tc+s]=t;
    
            Cover(tr,tc,dr,dc,s);//覆盖左上
            Cover(tr,tc+s,tr+s-1,tc+s,s);//覆盖右上
            Cover(tr+s,tc,tr+s,tc+s-1,s);//覆盖左下
            Cover(tr+s,tc+s,tr+s,tc+s,s);//覆盖右下
        }
        else if(dr<tr+s&&dc>=tc+s)//残缺在右上角
        {
            Board[tr+s-1][tc+s-1]=t;
            Board[tr+s][tc+s-1]=t;
            Board[tr+s][tc+s]=t;
    
            Cover(tr,tc,tr+s-1,tc+s-1,s);
            Cover(tr,tc+s,dr,dc,s);
            Cover(tr+s,tc,tr+s,tc+s-1,s);
            Cover(tr+s,tc+s,tr+s,tc+s,s);
        }
        else if(dr>=tr+s&&dc<tc+s)//残缺在左下
        {
            Board[tr+s-1][tc+s-1]=t;
            Board[tr+s-1][tc+s]=t;
            Board[tr+s][tc+s]=t;
    
            Cover(tr,tc,tr+s-1,tc+s-1,s);
            Cover(tr,tc+s,tr+s-1,tc+s,s);
            Cover(tr+s,tc,dr,dc,s);
            Cover(tr+s,tc+s,tr+s,tc+s,s);
        }
        else
        {
            Board[tr+s-1][tc+s-1]=t;
            Board[tr+s-1][tc+s]=t;
            Board[tr+s][tc+s-1]=t;
    
            Cover(tr,tc,tr+s-1,tc+s-1,s);
            Cover(tr,tc+s,tr+s-1,tc+s,s);
            Cover(tr+s,tc,tr+s,tc+s-1,s);
            Cover(tr+s,tc+s,dr,dc,s);
        }
    }
    
    void Print(int s)
    {
        for(int i=1;i<=s;i++)
        {
            for(int j=1;j<=s;j++)
                printf("%5d ",Board[i][j]);
            printf("
    ");
        }
    }
    
    int main()
    {
        int s=1,k,x,y;
        printf("输入2残缺棋盘的规模:2^k,k=");
        scanf("%d",&k);
        for(int i=1;i<=k;i++)
            s*=2;
        printf("输入棋盘残缺位置(x,y):");
        scanf("%d%d",&x,&y);
        Board[x][y]=0;
        Cover(1,1,x,y,s);
        Print(s);
        return 0;
    }
    




  • 相关阅读:
    SuperSocket框架中BinaryRequestInfo协议的使用
    UIImageView学习笔记
    UITextField学习小结
    Java数据结构相关类的实现原理
    Android 中把尺寸转换方法
    Win8 & WP8.1 轻型数据库
    隐私策略
    Windows 10(UWP)开发技巧
    【UWP】FFmpeg库的编译
    【UWP】拖拽列表项的排序功能实现
  • 原文地址:https://www.cnblogs.com/gaot/p/7709709.html
Copyright © 2020-2023  润新知