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;
    }
}
原文地址:https://www.cnblogs.com/jackwang-sparrow/p/13384779.html