zoukankan      html  css  js  c++  java
  • 棋盘覆盖问题(看完这个就好)

    棋盘覆盖(C语言)

    问题描述:
    如何应用分治法求解棋盘覆盖问题呢?分治的技巧在于如何划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋盘均包含一个特殊方格,从而将原问题分解为规模较小的棋盘覆盖问题。k>0时,可将2k×2k的棋盘划分为4个2(k-1)×2(k-1)的子棋盘,如图(a)所示。这样划分后,由于原棋盘只有一个特殊方格,所以,这4个子棋盘中只有一个子棋盘包含该特殊方格,其余3个子棋盘中没有特殊方格。为了将这3个没有特殊方格的子棋盘转化为特殊棋盘,以便采用递归方法求解,可以用一个L型骨牌覆盖这3个较小棋盘的会合处,如图(b)所示,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种划分策略,直至将棋盘分割为1×1的子棋盘。
    在这里插入图片描述
    思路:
    如何应用分治法求解棋盘覆盖问题呢?分治的技巧在于如何划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋盘均包含一个特殊方格,从而将原问题分解为规模较小的棋盘覆盖问题。k>0时,可将2k×2k的棋盘划分为4个2(k-1)×2(k-1)的子棋盘,这样划分后,由于原棋盘只有一个特殊方格,所以,这4个子棋盘中只有一个子棋盘包含该特殊方格,其余3个子棋盘中没有特殊方格。为了将这3个没有特殊方格的子棋盘转化为特殊棋盘,以便采用递归方法求解,可以用一个L型骨牌覆盖这3个较小棋盘的会合处,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种划分策略,直至将棋盘分割为1×1的子棋盘。——来自百度百科

    下面我来说说我的理解吧:

    首先,我们按照最小的模式,也就是 k=0 的时候,此时只有一个特殊方格没有三角方格需要放置,当然这种情况还是比较少的。
    接下来,就是 k=1 的时候,也就是有四个方格,无论特殊方格的位置在哪,我们都可以找到一个直角方格放置。

    接下来,就是 k 不断地递增,利用分治的思想,可以把大方格划分成小方格,划分到最后就剩下最后一个包含有特殊方格的四方格,这个时候,我们的直角方格该以哪种形式存在呢?对吧,面临的四边其实都是可以放置直角方格的。
    这个时候利用分治的思想,也就是说把原有的大方个,划分成四个相对小一个阶级的方格

    到最后就回到了递归的出口,也就是说,特殊方格分别在四方格的四个角上的情况。

    #include<stdio.h>
    #define n 8     //n为2^k
    int tr,tc;     //子棋盘的左上角第一个方格的横纵坐标
    int dr,dc;     //特殊方格的横纵坐标
    int size;
    int board[n][n];
    int tile=1;   //骨牌序号从1开始
    void input()
    {
        printf("输出棋盘长度:%d
    ",n);
        printf("请输入特殊棋盘的位置dr,dc:");
        scanf("%d,%d",&dr,&dc);
        board[dr][dc]=0;
    }
    void chess(int tr,int tc,int dr,int dc,int size)
    {
        if(size==1)
            return;
        int t=tile++;
        int s=size/2;
        if(dr<tr+s && dc<tc+s)     //特殊方格在左上方
            chess(tr,tc,dr,dc,s);
        else
        {
            board[tr+s-1][tc+s-1]=t;
            chess(tr,tc,tr+s-1,tc+s-1,s);
        }
        if(dr<tr+s && dc>=tc+s)     //特殊方格在右上方
            chess(tr,tc+s,dr,dc,s);
        else
        {
            board[tr+s-1][tc+s]=t;
            chess(tr,tc+s,tr+s-1,tc+s,s);
        }
        if(dr>=tr+s && dc<tc+s)     //特殊方格在左下方
            chess(tr+s,tc,dr,dc,s);
        else
        {
            board[tr+s][tc+s-1]=t;
            chess(tr+s,tc,tr+s,tc+s-1,s);
        }
        if(dr>=tr+s && dc>=tc+s)     //特殊方格在右下方
            chess(tr+s,tc+s,dr,dc,s);
        else
        {
            board[tr+s][tc+s]=t;
            chess(tr+s,tc+s,tr+s,tc+s,s);
        }
    }
    void display()    //输出二维数组
    {
        int i,j;
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                printf("%4d ",board[i][j]);
            }
            printf("
    
    ");
        }
    }
    void main()
    {
        input();
        chess(0,0,dr,dc,n);
        display();
    }
    

    代码应该可以看明白
    在这里插入图片描述

  • 相关阅读:
    FZU 2098 刻苦的小芳(卡特兰数,动态规划)
    卡特兰数总结
    FZU 1064 教授的测试(卡特兰数,递归)
    HDU 4745 Two Rabbits(区间DP,最长非连续回文子串)
    Java 第十一届 蓝桥杯 省模拟赛 正整数的摆动序列
    Java 第十一届 蓝桥杯 省模拟赛 反倍数
    Java 第十一届 蓝桥杯 省模拟赛 反倍数
    Java 第十一届 蓝桥杯 省模拟赛 反倍数
    Java 第十一届 蓝桥杯 省模拟赛 凯撒密码加密
    Java 第十一届 蓝桥杯 省模拟赛 凯撒密码加密
  • 原文地址:https://www.cnblogs.com/Indomite/p/14195238.html
Copyright © 2011-2022 走看看