zoukankan      html  css  js  c++  java
  • 啊哈,算法自学记——6th

    深度优先搜索

    全排列问题:
    理解深度优先搜索的关键在于:
    解决当下该如何做,至于下一步该如何做则与当下该如何做是一样的的操作。
    深度优先搜索基本模型

    void dfs(int step)
    {
    	判断边界
    	尝试每一种可能for(int i=1;i<=n;i++)
    	{
    		继续下一步dfs(step+1);
    	}
    	return;
    }
    
    #include <stdio.h>
    
    int a[10],book[10],n;//C语言的全局变量在没有赋值前默认为0,所以数组不用赋值了
    
    void dfs(int step)//step表示站在第几个盒子面前
    {
        int i;
        if(step==(n+1))//表示前面n 个盒子已经安排好了
        {
            //输出一种排列,(1-n盒子中的扑克牌编号)
            for (int  i = 1; i <= n; i++)
            {
                printf("-%d",a[i]);  
            }
            printf("
    ");
            return;//返回之前一步,也即最近调用dfs函数的地方
        }
        //此时站在第step个盒子面前,应该放那张牌呢?
        //按照 1-2-3-4-----n的顺序一一尝试
        for (int i = 1; i <= n; i++)
        {
            if(book[i]==0)//如果扑克i还在手上
            {
                //开始 常识使用扑克i
                a[step]=i;//将扑克i放入第step个盒子中
                book[i]=1;//表示扑克i已经不在手中
    
                //第step个盒子已经放好扑克牌,接下来需要走到下一个盒子面前
                dfs(step+1);//通过函数的递归调用来实现
                book[i]=0;//将刚才常识的扑克牌收回,才能进行下一次的常识
            }
        }
        return;
    }
    
    
    int main(int argc, char const *argv[])
    {
        printf("Input a int num between 0-9:
    ");
        scanf("%d",&n);
        dfs(1);//首先站到第一个盒子面前
        return 0;
    }
    
    

    运行结果:
    在这里插入图片描述

    用深度优先搜索解决:口口口+口口口=口口口的问题
    (填入1~9,每个只能用一次,使等式成立)

    #include <stdio.h>
    
    /*解决abc+efg=hij的问题
    *数字为1~9
    */
    
    int n,a[10],book[10];//全局变量默认值为0
    
    
    void dfs(int step)
    {
        int i;
        if(step==10)//n 个数,此时说明前面的n 个数已经安排好了
        {
            if (((a[1]*100+a[2]*10+a[3])+(a[4]*100+a[5]*10+a[6]))==(a[7]*100+a[8]*10+a[9]))
            {
                printf("%d%d%d+%d%d%d=%d%d%d
    ",a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);//打印已经安排好的排列
                n++;
            }
             return;
        }
    
        for(int i=1;i<=9;i++)
        {
            if (book[i]==0)//说明牌还在手上     
            {
                a[step]=i;
                book[i]=1;
    
                dfs(step+1);
                book[i]=0;
            }
            
        }
        return;
    }
    
    int main(int argc, char const *argv[])
    {
        dfs(1);
        printf("Total:%d
    ",n/2);
        return 0;
    }
    
    

    运行结果:
    在这里插入图片描述

    深度优先搜索,迷宫寻找小哈:

    在这里插入图片描述
    最开始在(1,1)只能向右走或者向下走,一个小哼只能向下走或者向右走,我们这里一个一个试,先让小哼向右走,走不通的时候在想下走,这里我们规定走的方向为: 右、下、左、上

    用深度优先搜索来解决:
    dfs()函数解决的功能是,当前应该怎么办,而当小哼在某个点的时候应该处理的是:先判断是否已经到达小哈的位置,如果没有到达则找到下一步的位置。

    #include <stdio.h>
    
    int m,n,q,p,min=999999;
    
    int a[51][51],book[51][51];
    
    void dfs(int x,int y,int step)
    {
        int next[4][2]={//这里的x和y代表的是行和列,
            {0,1},//向右走**也即行不变,列+1
            {1,0},//向下走**列不变,行+1
            {0,-1},//向左走**行不变,列-1
            {-1,0}//向上走**行-1,列不变
        };
    
        int tx,ty,k;
        //判断是否到达小哈的位置
        if(x==p && y==q)
        {
            if(step<min)
                min=step;
            return;
        }
    
        //枚举四种走法,方向为右、下、左、上
        for (k = 0; k <= 3; k++)
        {
            //计算下一个点的坐标
            /*当k=0时,tx=x+0;ty=y+1;
             *当k=1时,tx=x+1;ty=y+0;
             *当k=2时,tx=x+0;ty=y-1;
             *当k=3时,tx=x-1;ty=y+0;
            */
            tx=x+next[k][0];
            ty=y+next[k][1];
    
            //判断是否越界
            if (tx<1||ty<1||tx>n||ty>m) 
            {
                continue;//下面的代码不执行,重新回归继续for循环
            }
            //判断该点是否为障碍物或者已经在路径之中
            if (a[tx][ty]==0 && book[tx][ty]==0)//如果该点,也就是计算出来的下一个点,既不是障碍物又不在已走过的路径中
            {
                book[tx][ty]=1;//标记该点已经走过
                dfs(tx,ty,step+1);//开始尝试下一个点,尝试每一种可能
                book[tx][ty]=0;//尝试结束, 取消这个点的标记
            } 
        }
        return;
    }
    
    int main(int argc, char const *argv[])
    {
        int i,j,startx,starty;
        //读入迷宫的行和列,n为行,m为列
        printf("Input the map size:
    ");
        scanf("%d %d",&n,&m);
        //读取迷宫
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                scanf("%d",&a[i][j]);//二维数组a用来保存地图
            }
        }
    
        //读入迷宫的起点和终点
        printf("Input the start and the ending:
    ");
        scanf("%d %d %d %d",&startx,&starty,&p,&q);
        //从起点开始搜索 
        book[startx][starty]=1;//标记起点已经在路径中,防止重复走----二维数组book用来存储已经走过的点
    
        dfs(startx,starty,0);//从起点开始,走过的路程为0
        printf("The min length is: %d
    ",min);
        return 0;
    }
    
    

    运行结果:
    在这里插入图片描述

  • 相关阅读:
    Java 位运算(移位、位与、或、异或、非)
    负数的二进制表示方法(正数:原码、负数:补码)
    MacOS X终端里SSH会话管理
    Mac软件分享:上小巧实用的GIF格式录屏软件 LICEcap
    问题追踪:ImageView执行缩放动画ScaleAnimation之后,图像显示不全的问题。
    自定义res/anim加载类,加载自定义Interpolator
    原文翻译 Android_Develop_API Guides_Animation Resources(动画资源)
    OAuth2.0详解
    Grails框架使用指南
    Groovy语言学习汇总
  • 原文地址:https://www.cnblogs.com/hhsxy/p/14018429.html
Copyright © 2011-2022 走看看