• 深搜——蓝桥杯之方格填数,寒假作业


    问题描述:

    方格填数


    如下的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;
    }
  • 相关阅读:
    C#Type类中的IsAssignableFrom、IsInstanceOfType、IsSubclassOf
    C# IsAssignableFrom & IsInstanceOfType & IsSubclassOf & Is
    VS2017桌面应用程序打包成.msi或者.exe
    C# 10个常用特性
    ADO.NET 的六大对象及其关系图
    Expression表达式树(C#)
    表达式树 Expression Trees
    特性 Attribute
    C# 特性(attribute)
    Vue中使用axios
  • 原文地址:https://www.cnblogs.com/NikkiNikita/p/9450767.html
Copyright © 2020-2023  润新知