zoukankan      html  css  js  c++  java
  • DFS【搜索1】

    DFS模板

    void dfs(int depth)//depth表示当前的层数(或深度)
    {
        if(depth>n)//到达叶子节点,该路已走到尽头
            return;
        for(int i=1;i<=n;i++)//n表示最大的值,即最大深度为n
        {
            if(b[i]==0)//b数组表示探索的状态,1表示已被探索,0表示尚未被探索
            {
                b[i]=1;//标记当前的b[i]已被探索
                a[level]=i;//记录当前的节点值
                dfs(level+1);//进一步的搜索
                b[i]=0;//还原当前的b[i]元素被探索的状态
            }
        }
    }

    数字型搜索


    全排列问题

    题目描述

    排列与组合是常用的数学方法。
    先给一个正整数 ( 1 < = n < = 10 )
    例如n=3,所有组合,并且按字典序输出:
    1 2 3
    1 3 2
    2 1 3
    2 3 1
    3 1 2
    3 2 1 

    输入

    输入一个整数n(  1<=n<=10)

    输出

    输出所有全排列

    每个全排列一行,相邻两个数用空格隔开(最后一个数后面没有空格)

    样例输入 Copy

    3
    

    样例输出 Copy

    1 2 3
    1 3 2
    2 1 3
    2 3 1
    3 1 2
    3 2 1
    #include<bits/stdc++.h>
    #include<queue>
    using namespace std;
    const int N=100;
    typedef long long ll;
    int n,a[10010],b[10010];
    void print()
    {
        for(int i=1;i<=n;i++)
        {
            printf("%5d",a[i]);
        }
        cout<<endl;
    }
    void dfs(int level)
    {
        if(level==n+1)
        {
            print();
            return;
        }
        for(int i=1;i<=n;i++)
        {
            if(b[i]==0)
            {
                b[i]=1;
                a[level]=i;
                dfs(level+1);
                b[i]=0;
            }
        }
    }
    int main()
    {
        cin>>n;
        dfs(1);
    }

    【牛客】 Factorial

    1、暴力解题,代码略;

    2、dfs解题(重点),万物皆可搜,有点类似斐波那契递归

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll maxn=1e5+10;
    #define IO ios::sync_with_stdio(false), cin.tie(0)
    #define T int t ;cin >> t;while(t--)
    ll a[maxn];
    ll dfs(ll n)
    {
        if(n<=1)
        {
            return 1;
        }
        else
        {
            return dfs(n-1)*n;
        }
    }
    int main()
    {
        T
        {
            ll n;
            scanf("%lld",&n);
            printf("%lld
    ",dfs(n));
        }
    }

    地图型搜索


    n皇后问题

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int n,y[100010],s,ans[100010];
    bool check(int x)//剪枝,判断两点的位置\
    两点的斜率的绝对值不得等于1;两点不得在同一水平线上(包括同一行和同一列)
    {
        for(int i=1;i<x;i++)//i本身就是指行号,y[i]表示对应的列号
        {
            if(abs(x-i)==abs(y[x]-y[i])||y[x]==y[i]||x==i)
            {
                return 0;
            }
        }
        return 1;
    }
    void dfs(int num)
    {
        if(num>n)//越界处理
        {
            s++;
            return;
        }
        for(int i=1;i<=n;i++)
        {
            y[num]=i;//将当前的行号赋值给第num个皇后
            if(check(num))
                dfs(num+1);//进行下一步的搜索
        }
    }
    int main()
    {
        for(int i=1;i<=10;i++)
        {
            n=i;
            s=0;
            dfs(1);
            ans[i]=s;
        }
        while(~scanf("%d",&n)&&n)
            printf("%d
    ",ans[n]);
    }

     POJ3083 Children of the Candy Corn

    左搜索(Ldfs)+右搜索(Rdfs)+最短路径搜索(bfs)

    搜索方位

     左搜索:

    始终靠左搜索,如果左边是墙#,那就往上面搜索;上面是墙#,那就往右边搜索;右边是墙#则返回之前的位置,即往后搜索。

    右搜索:

    bfs最短路搜索:

    创建队列,在一个点的周围的同一层搜索(这是与DFS的区别最大之处),用vis数组标记是否被搜索过

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int N=55;
    char mp[41][41];
    int vis[41][41];
    int m,n,f,ans1,ans2;
    int head_x,head_y,tail_x,tail_y;
    int dir1[4][2]= {-1,0,1,0,0,1,0,-1};
    struct node
    {
        int x,y,step;
    } head,tail;
    bool judge(int xx,int yy)
    {
        if(xx>=1&&xx<=m&&yy>=1&&yy<=n&&mp[xx][yy]!='#'&&vis[xx][yy]==0)
            return true;
        return false;
    }
    void dfs1(int xx,int yy,int step,int dir)//逆时针走法
    {
        if(f==1)
            return;
        if(xx==tail_x&&yy==tail_y)
        {
            f=1;
            ans1=step;
            return;
        }
        if(dir==1)//右上左下
        {
            if(judge(xx+1,yy)) dfs1(xx+1,yy,step+1,4);
            if(judge(xx,yy-1)) dfs1(xx,yy-1,step+1,1);
            if(judge(xx-1,yy)) dfs1(xx-1,yy,step+1,2);
            if(judge(xx,yy+1)) dfs1(xx,yy+1,step+1,3);
        }
        else if(dir==2)//上左下右
        {
            if(judge(xx,yy-1)) dfs1(xx,yy-1,step+1,1);
            if(judge(xx-1,yy)) dfs1(xx-1,yy,step+1,2);
            if(judge(xx,yy+1)) dfs1(xx,yy+1,step+1,3);
            if(judge(xx+1,yy)) dfs1(xx+1,yy,step+1,4);
        }
        else if(dir==3)//左下右上
        {
    
            if(judge(xx-1,yy)) dfs1(xx-1,yy,step+1,2);
            if(judge(xx,yy+1)) dfs1(xx,yy+1,step+1,3);
            if(judge(xx+1,yy)) dfs1(xx+1,yy,step+1,4);
            if(judge(xx,yy-1)) dfs1(xx,yy-1,step+1,1);
        }
        else//右下上左
        {
            if(judge(xx,yy+1)) dfs1(xx,yy+1,step+1,3);
            if(judge(xx+1,yy)) dfs1(xx+1,yy,step+1,4);
            if(judge(xx,yy-1)) dfs1(xx,yy-1,step+1,1);
            if(judge(xx-1,yy)) dfs1(xx-1,yy,step+1,2);
        }
    }
    void dfs2(int xx,int yy,int step,int dir)
    {
        if(f==1)
        {
            return;
        }
        if(xx==tail_x&&yy==tail_y)
        {
            f=1;
            ans2=step;
            return;
        }
        if(dir==1)
        {
            if(judge(xx-1,yy)) dfs2(xx-1,yy,step+1,2);
            if(judge(xx,yy-1)) dfs2(xx,yy-1,step+1,1);
            if(judge(xx+1,yy)) dfs2(xx+1,yy,step+1,4);
            if(judge(xx,yy+1)) dfs2(xx,yy+1,step+1,3);
        }
        else if(dir==2)
        {
            if(judge(xx,yy+1)) dfs2(xx,yy+1,step+1,3);
            if(judge(xx-1,yy)) dfs2(xx-1,yy,step+1,2);
            if(judge(xx,yy-1)) dfs2(xx,yy-1,step+1,1);
            if(judge(xx+1,yy)) dfs2(xx+1,yy,step+1,4);
    
        }
        else if(dir==3)
        {
            if(judge(xx+1,yy)) dfs2(xx+1,yy,step+1,4);
            if(judge(xx,yy+1)) dfs2(xx,yy+1,step+1,3);
            if(judge(xx-1,yy)) dfs2(xx-1,yy,step+1,2);
            if(judge(xx,yy-1)) dfs2(xx,yy-1,step+1,1);
        }
        else
        {
            if(judge(xx,yy-1)) dfs2(xx,yy-1,step+1,1);
            if(judge(xx+1,yy)) dfs2(xx+1,yy,step+1,4);
            if(judge(xx,yy+1)) dfs2(xx,yy+1,step+1,3);
            if(judge(xx-1,yy)) dfs2(xx-1,yy,step+1,2);
        }
    }
    int bfs()
    {
        queue<node> q;
        while(!q.empty())
        {
            q.pop();
        }
        head.x=head_x,head.y=head_y,head.step=1;
        q.push(head);
        vis[head_x][head_y]=1;
        while(!q.empty())
        {
            head=q.front();
            q.pop();
            if(head.x==tail_x&&head.y==tail_y)
            {
                return head.step;
            }
            for(int i=0; i<4; i++)
            {
                tail.x=head.x+dir1[i][0];
                tail.y=head.y+dir1[i][1];
                if(judge(tail.x,tail.y))
                {
                    tail.step=head.step+1;
                    vis[tail.x][tail.y]=1;
                    q.push(tail);
                }
            }
        }
        return 0;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            memset(vis,0,sizeof vis);
            scanf("%d%d",&n,&m);
            for(int i=1; i<=m; i++)
            {
                for(int j=1; j<=n; j++)
                {
                    scanf(" %c",&mp[i][j]);
                    if(mp[i][j]=='S')
                    {
                        head_x=i;
                        head_y=j;
                    }
                    if(mp[i][j]=='E')
                    {
                        tail_x=i;
                        tail_y=j;
                    }
                }
            }
            f=0;
            ans1=0;
            dfs1(head_x,head_y,1,1);
            f=0;
            ans2=0;
            dfs2(head_x,head_y,1,1);
            int ans3=bfs();
            printf("%d %d %d
    ",ans1,ans2,ans3);
        }
    }

     棋盘问题

    n表示棋盘的大小是n*n,m表示棋子的数量,结束dfs的条件就是当前的棋子数量大于等于m(因为初始的0就已经存在1颗棋子了)。

    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #define IO ios::sync_with_stdio(false), cin.tie(0)
    typedef long long ll;
    using namespace std;
    const ll maxn=1e5+10;
    char mp[100][100];
    bool vis[100];
    ll n,m,s;
    void dfs(ll x,ll y)
    {
        if(y>=m)
        {
            s++;
            return;
        }
        for(ll i=x; i<n; i++)
            for(ll j=0; j<n; j++)
            {
                if(vis[j]==false&&mp[i][j]=='#')
                {
                    vis[j]=true;
                    dfs(i+1,y+1);
                    vis[j]=false;
                }
            }
    }
    int main()
    {
        while(1)
        {
            scanf("%lld%lld",&n,&m);
            if(n==-1&&m==-1)
                break;
            memset(vis,0,sizeof vis);
            memset(mp,0,sizeof mp);
            for(ll i=0; i<n; i++)scanf("%s",mp[i]);
            s=0;
            dfs(0,0);
            cout<<s<<endl;
        }
    }

    Oil Deposit

    #include <bits/stdc++.h>
    using namespace std ;
    typedef long long ll;
    ll m,n;
    char mp[110][110];
    ll dir[8][2]= { {0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1} };//方向可以任意,当前方向见图
    void dfs(ll x,ll y)
    {
        mp[x][y]='*';//把当前的@转换成*,避免重复查找
        for(ll i=0; i<8; i++)
        {
            ll xx=x+dir[i][0],yy=y+dir[i][1];
            if(xx>=1&&xx<=m&&yy>=1&&yy<=n&&mp[xx][yy]=='@')
            {
                dfs(xx,yy);
            }
        }
        return;//递归结束
    }
    int main()
    {
        while(~scanf("%lld%lld",&m,&n)&&n&&m)
        {
            ll sum=0;
            for(ll i=1; i<=m; i++)
            {
                for(ll j=1;j<=n;j++)
                {
                    cin>>mp[i][j];
                    //scanf(" %c",&mp[i][j]);
                    //两种读入方式均可,要注意的是,用scanf()读入的话,需要在%c之前加入一个空格,这是专门用来吸收"
    "
                }
            }
            for(ll i=1; i<=m; i++)
            {
                for(ll j=1; j<=n; j++)
                {
                    if(mp[i][j]=='@')
                    {
                        dfs(i,j);
                        sum++;
                    }
                }
            }
            cout<<sum<<endl;
        }
    }
  • 相关阅读:
    迷宫
    【NOIP2001普及组】最大公约数和最小公倍数问题
    latex online tool
    连续自然数和
    又是毕业季Ⅰ
    区间素数
    【AHOI2005】约数研究
    【NOIP2011提高组】计算系数
    【NOIP2012普及组】寻宝
    plsql 导出oracle数据库
  • 原文地址:https://www.cnblogs.com/jackwang-sparrow/p/13384779.html
Copyright © 2011-2022 走看看