zoukankan      html  css  js  c++  java
  • 深搜——蓝桥杯之方格填数,寒假作业

    问题描述:

    方格填数


    如下的10个格子
       +--+--+--+
       |  |  |  |
    +--+--+--+--+
    |  |  |  |  |
    +--+--+--+--+
    |  |  |  |
    +--+--+--+


    (如果显示有问题,也可以参看下图)


    填入0~9的数字。要求:连续的两个数字不能相邻。
    (左右、上下、对角都算相邻)


    一共有多少种可能的填数方案?


    请填写表示方案数目的整数。

    注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

    首先,不必花心思考虑怎么把这个图形在程序中表现出来,一个一维数组就可以搞定,我们这样做:

    自上而下,从左向右分别给这些单元格标记为 a[1],a[2],...,a[10]。

    要做到题述要求,对于 a[1],只需要 a[1] 和 a[2],a[4],a[5],a[6] 之间的绝对值大于 1 即可。对其他位置亦是如此,如果填写的不符合要求就回溯,和深搜的思想一样,如果不是很理解深搜,请看这篇文章:

    http://blog.csdn.net/eliminatedacmer/article/details/79334903

    我们只需要将符合题意的结果找出来就可以了:

    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    int count = 0;
    int a[12],b[12];
    void Check()
    {
        if(abs(a[1]-a[2])>1 && abs(a[1]-a[4])>1 && abs(a[1]-a[5])>1 && abs(a[1]-a[6])>1 &&
           abs(a[2]-a[3])>1 && abs(a[2]-a[5])>1 && abs(a[2]-a[6])>1 && abs(a[2]-a[7])>1 &&
           abs(a[3]-a[6])>1 && abs(a[3]-a[7])>1 &&
           abs(a[4]-a[5])>1 && abs(a[4]-a[8])>1 && abs(a[4]-a[9])>1 &&
           abs(a[5]-a[6])>1 && abs(a[5]-a[8])>1 && abs(a[5]-a[9])>1 && abs(a[5]-a[10])>1 &&
           abs(a[6]-a[7])>1 && abs(a[6]-a[9])>1 && abs(a[6]-a[10])>1 &&
           abs(a[7]-a[10])>1 &&
           abs(a[8]-a[9])>1 &&
           abs(a[9]-a[10])>1)
            {
                count++;
            }
    }
    void Fill_numbers(int x)
    {
        if(x > 10)
        {
            Check();
            return;
        }
    
        for(int i = 0;i<10;i++)
        {
            if(b[i] == 0)
            {
                b[i] = 1;
                a[x] = i;
                Fill_numbers(x+1);
                b[i] = 0;
            }
    
        }
    }
    
    int main()
    {
        Fill_numbers(1);
        cout<<count;
        return 0;
    }
     

    接下来是寒假作业,请读者体会这两者思路上的差异。

    问题描述:

    寒假作业


    现在小学的数学题目也不是那么好玩的。
    看看这个寒假作业:


       □ + □ = □
       □ - □ = □
       □ × □ = □
       □ ÷ □ = □
       

       (如果显示不出来,可以参见下图)

       
    每个方块代表1~13中的某一个数字,但不能重复。
    比如:
     6  + 7 = 13
     9  - 8 = 1
     3  * 4 = 12
     10 / 2 = 5


    以及: 
     7  + 6 = 13
     9  - 8 = 1
     3  * 4 = 12
     10 / 2 = 5


    就算两种解法。(加法,乘法交换律后算不同的方案)
     
    你一共找到了多少种方案?


    请填写表示方案数目的整数。

    注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

    对于这个问题我们很容易联想到上面那种解法,即:

    #include <iostream>
    #define _MAX 13
    
    using namespace std;
    
    int count = 0;
    int num[_MAX];
    int vis[_MAX];
    
    void dfs(int n)
    {
        int i = 0;
        if (n >= _MAX)
        {
            if (num[0] + num[1] == num[2] && num[3] - num[4] == num[5]&&num[6] * num[7] == num[8]&&num[10] * num[11] == num[9])
                count++;
            return ;
        }
        for (; i < _MAX; i++)
        {
            if (!vis[i])
            {
                vis[i] = 1;
                num[n] = i + 1;
                dfs(n + 1);
                vis[i] = 0;
            }
        }
        return ;
    }
    
    int main()
    {
        dfs(0);
        cout<<count;
        return 0;
    }
     

    这种做法当然是正确的,但是如果你运行了一遍就会知道,它要得出正确的结果,需要长达几分钟的运行时间,因为我们是在所有数都填好之后才开始进行判断,而且这里有12个空,13个数字,因此大大增加了计算量,因此,我们需要优化算法,让它不要进行多余的计算,也就是说,如果第一个表达式都不满足的情况下,以后所有后续的填数工作我们都不需要做了。即:

    #include <iostream>
    #define _MAX 13
    
    using namespace std;
    
    int count = 0;
    int num[_MAX];
    int vis[_MAX];
    
    int Check(int n)
    {
        if (n == 2)
        {
            if (num[0] + num[1] == num[2])
            {
                return 1;
            }
        }
        else if (n == 5)
        {
            if (num[3] - num[4] == num[5])
            {
                return 1;
            }
        }
        else if (n == 8)
        {
            if (num[6] * num[7] == num[8])
            {
                return 1;
            }
        }
        else if (n == 11)
        {
            if (num[10] * num[11] == num[9])
            {
                count++;
                return 1;
            }
        }
        else
        {
            return 1;
        }
        return 0;
    }
    
    void dfs(int n)
    {
        int i = 0;
        if (n >= _MAX)
        {
            return ;
        }
        for (; i < _MAX; i++)
        {
            if (!vis[i])
            {
                vis[i] = 1;
                num[n] = i + 1;
                if (!Check(n)) 
                {
                    vis[i] = 0;
                    continue;
                }
                dfs(n + 1);
                vis[i] = 0;
            }
        }
        return ;
    }
    
    int main()
    {
        dfs(0);
        cout<<count;
        return 0;
    }
  • 相关阅读:
    服务端实现url网页截屏、HTML保存为高质量PDF[puppeteer]
    网页保存为图片[rasterizeHTML]
    SortedList<T,K>,SortedDictionary<T,K>,Dictionay<T,K>用法区别
    svn实现类似git stash及git stash pop的功能
    MSBuild报错及找不到AxImp.exe或LC.exe问题
    记一个ios下text-overflow: ellipsis 与 text-align: justify 冲突的问题
    Chrome devtools inspect后打开空白解决办法
    Oracle长时间使用导致连接变慢且频繁报无法找到监听程序的错误
    vscode+vue不得不用的插件和不得不添加的配置
    初识vscode+vue
  • 原文地址:https://www.cnblogs.com/NikkiNikita/p/9450767.html
Copyright © 2011-2022 走看看