zoukankan      html  css  js  c++  java
  • 第七届C/C++B-方格填数 DFS

    方格填数


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


    (如果显示有问题,也可以参看【图1.jpg】)


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


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


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

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




    思路:

    DFS

    优化:

    因为搜索的位置是按照很纵坐标依次增大来的,所以原来设定的8个方向就可以缩短为4个方向。

    测试结果:1580

    代码:

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int ans[3][4];
    bool bns[10];
    int dir[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
    int sum=0;
    void init()
    {
        memset(ans,-1,sizeof(ans));
        memset(bns,false,sizeof(bns));
    }
    bool check(int x, int y, int num)
    {
        int sx,sy;
        for(int i=0;i<=7;i++)
        {
            sx=x+dir[i][0];
            sy=y+dir[i][1];
            if(sx<0||sx>2||sy<0||sy>3)//越界跳过
                continue;
            if(ans[sx][sy]==-1)
                continue;
            if(fabs(ans[sx][sy]-num)==1)
                return false;
        }
        return true;
    }
    void dfs(int x, int y)//位置的横坐标、纵坐标
    {
        for(int i=0;i<=9;i++)
        {
            if(!bns[i]&&check(x,y,i))//没有使用过i,并且检查可用
            {
                bns[i]=true;
                ans[x][y]=i;
                if(x==2&&y==2)
                {
                    sum++;
                }
                else
                {
                    if(y!=3)
                        dfs(x,y+1);
                    else
                    {
                        dfs(x+1,0);
                    }
                }
                bns[i]=false;
                ans[x][y]=-1;
            }
        }
    }
    int main()
    {
        init();
        dfs(0,1);
        printf("%d
    ",sum);//1580
        return 0;
    }
    

    优化之后:

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int ans[3][4];
    bool bns[10];
    int dir[4][2]={{-1,-1},{-1,0},{-1,1},{0,-1}};
    int sum=0;
    void init()
    {
        memset(ans,-1,sizeof(ans));
        memset(bns,false,sizeof(bns));
    }
    bool check(int x, int y, int num)
    {
        int sx,sy;
        for(int i=0;i<=3;i++)
        {
            sx=x+dir[i][0];
            sy=y+dir[i][1];
            if(sx<0||sx>2||sy<0||sy>3)//越界跳过
                continue;
            if(ans[sx][sy]==-1)
                continue;
            if(fabs(ans[sx][sy]-num)==1)
                return false;
        }
        return true;
    }
    void dfs(int x, int y)//位置的横坐标、纵坐标
    {
        for(int i=0;i<=9;i++)
        {
            if(!bns[i]&&check(x,y,i))//没有使用过i,并且检查可用
            {
                bns[i]=true;
                ans[x][y]=i;
                if(x==2&&y==2)
                {
                    sum++;
                }
                else
                {
                    if(y!=3)
                        dfs(x,y+1);
                    else
                    {
                        dfs(x+1,0);
                    }
                }
                bns[i]=false;
                ans[x][y]=-1;//优化之后这里就不用恢复现场也可以
            }
        }
    }
    int main()
    {
        init();
        dfs(0,1);
        printf("%d
    ",sum);//1580
        return 0;
    }
    


  • 相关阅读:
    UML模型
    Clustering vs. Witness SQL Server AlwaysOn vs. Database Mirroring
    工具软件推荐
    用StyleCop规范团队代码
    个人整理的Knockout.js文档,有兴趣的朋友可以直接下载!
    认识ASP.NET MVC的5种AuthorizationFilter
    深入探讨ASP.NET MVC的筛选器
    如何在调用WCF服务之前弹出一个确认对话框?
    愤青,哀哉我本愤青幸哉
    vs2005入门 .Net2.0视频教程 之 DataSet深入使用 [视频]
  • 原文地址:https://www.cnblogs.com/lemonbiscuit/p/7776014.html
Copyright © 2011-2022 走看看