DFS模板

void dfs(int depth)//depth表示当前的层数(或深度)
{
if(depth>n)//到达叶子节点,该路已走到尽头
return;
for(int i=;i<=n;i++)//n表示最大的值,即最大深度为n
{
if(b[i]==)//b数组表示探索的状态,1表示已被探索,0表示尚未被探索
{
b[i]=;//标记当前的b[i]已被探索
a[level]=i;//记录当前的节点值
dfs(level+);//进一步的搜索
b[i]=;//还原当前的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=;
typedef long long ll;
int n,a[],b[];
void print()
{
for(int i=;i<=n;i++)
{
printf("%5d",a[i]);
}
cout<<endl;
}
void dfs(int level)
{
if(level==n+)
{
print();
return;
}
for(int i=;i<=n;i++)
{
if(b[i]==)
{
b[i]=;
a[level]=i;
dfs(level+);
b[i]=;
}
}
}
int main()
{
cin>>n;
dfs();
}

【牛客】 Factorial

1、暴力解题,代码略;

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

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e5+;
#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<=)
{
return ;
}
else
{
return dfs(n-)*n;
}
}
int main()
{
T
{
ll n;
scanf("%lld",&n);
printf("%lld\n",dfs(n));
}
}

地图型搜索


n皇后问题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,y[],s,ans[];
bool check(int x)//剪枝,判断两点的位置\\
两点的斜率的绝对值不得等于1;两点不得在同一水平线上(包括同一行和同一列)
{
for(int i=;i<x;i++)//i本身就是指行号,y[i]表示对应的列号
{
if(abs(x-i)==abs(y[x]-y[i])||y[x]==y[i]||x==i)
{
return ;
}
}
return ;
}
void dfs(int num)
{
if(num>n)//越界处理
{
s++;
return;
}
for(int i=;i<=n;i++)
{
y[num]=i;//将当前的行号赋值给第num个皇后
if(check(num))
dfs(num+);//进行下一步的搜索
}
}
int main()
{
for(int i=;i<=;i++)
{
n=i;
s=;
dfs();
ans[i]=s;
}
while(~scanf("%d",&n)&&n)
printf("%d\n",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=;
char mp[][];
int vis[][];
int m,n,f,ans1,ans2;
int head_x,head_y,tail_x,tail_y;
int dir1[][]= {-,,,,,,,-};
struct node
{
int x,y,step;
} head,tail;
bool judge(int xx,int yy)
{
if(xx>=&&xx<=m&&yy>=&&yy<=n&&mp[xx][yy]!='#'&&vis[xx][yy]==)
return true;
return false;
}
void dfs1(int xx,int yy,int step,int dir)//逆时针走法
{
if(f==)
return;
if(xx==tail_x&&yy==tail_y)
{
f=;
ans1=step;
return;
}
if(dir==)//右上左下
{
if(judge(xx+,yy)) dfs1(xx+,yy,step+,);
if(judge(xx,yy-)) dfs1(xx,yy-,step+,);
if(judge(xx-,yy)) dfs1(xx-,yy,step+,);
if(judge(xx,yy+)) dfs1(xx,yy+,step+,);
}
else if(dir==)//上左下右
{
if(judge(xx,yy-)) dfs1(xx,yy-,step+,);
if(judge(xx-,yy)) dfs1(xx-,yy,step+,);
if(judge(xx,yy+)) dfs1(xx,yy+,step+,);
if(judge(xx+,yy)) dfs1(xx+,yy,step+,);
}
else if(dir==)//左下右上
{ if(judge(xx-,yy)) dfs1(xx-,yy,step+,);
if(judge(xx,yy+)) dfs1(xx,yy+,step+,);
if(judge(xx+,yy)) dfs1(xx+,yy,step+,);
if(judge(xx,yy-)) dfs1(xx,yy-,step+,);
}
else//右下上左
{
if(judge(xx,yy+)) dfs1(xx,yy+,step+,);
if(judge(xx+,yy)) dfs1(xx+,yy,step+,);
if(judge(xx,yy-)) dfs1(xx,yy-,step+,);
if(judge(xx-,yy)) dfs1(xx-,yy,step+,);
}
}
void dfs2(int xx,int yy,int step,int dir)
{
if(f==)
{
return;
}
if(xx==tail_x&&yy==tail_y)
{
f=;
ans2=step;
return;
}
if(dir==)
{
if(judge(xx-,yy)) dfs2(xx-,yy,step+,);
if(judge(xx,yy-)) dfs2(xx,yy-,step+,);
if(judge(xx+,yy)) dfs2(xx+,yy,step+,);
if(judge(xx,yy+)) dfs2(xx,yy+,step+,);
}
else if(dir==)
{
if(judge(xx,yy+)) dfs2(xx,yy+,step+,);
if(judge(xx-,yy)) dfs2(xx-,yy,step+,);
if(judge(xx,yy-)) dfs2(xx,yy-,step+,);
if(judge(xx+,yy)) dfs2(xx+,yy,step+,); }
else if(dir==)
{
if(judge(xx+,yy)) dfs2(xx+,yy,step+,);
if(judge(xx,yy+)) dfs2(xx,yy+,step+,);
if(judge(xx-,yy)) dfs2(xx-,yy,step+,);
if(judge(xx,yy-)) dfs2(xx,yy-,step+,);
}
else
{
if(judge(xx,yy-)) dfs2(xx,yy-,step+,);
if(judge(xx+,yy)) dfs2(xx+,yy,step+,);
if(judge(xx,yy+)) dfs2(xx,yy+,step+,);
if(judge(xx-,yy)) dfs2(xx-,yy,step+,);
}
}
int bfs()
{
queue<node> q;
while(!q.empty())
{
q.pop();
}
head.x=head_x,head.y=head_y,head.step=;
q.push(head);
vis[head_x][head_y]=;
while(!q.empty())
{
head=q.front();
q.pop();
if(head.x==tail_x&&head.y==tail_y)
{
return head.step;
}
for(int i=; i<; i++)
{
tail.x=head.x+dir1[i][];
tail.y=head.y+dir1[i][];
if(judge(tail.x,tail.y))
{
tail.step=head.step+;
vis[tail.x][tail.y]=;
q.push(tail);
}
}
}
return ;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(vis,,sizeof vis);
scanf("%d%d",&n,&m);
for(int i=; i<=m; i++)
{
for(int j=; 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=;
ans1=;
dfs1(head_x,head_y,,);
f=;
ans2=;
dfs2(head_x,head_y,,);
int ans3=bfs();
printf("%d %d %d\n",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+;
char mp[][];
bool vis[];
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=; j<n; j++)
{
if(vis[j]==false&&mp[i][j]=='#')
{
vis[j]=true;
dfs(i+,y+);
vis[j]=false;
}
}
}
int main()
{
while()
{
scanf("%lld%lld",&n,&m);
if(n==-&&m==-)
break;
memset(vis,,sizeof vis);
memset(mp,,sizeof mp);
for(ll i=; i<n; i++)scanf("%s",mp[i]);
s=;
dfs(,);
cout<<s<<endl;
}
}

Oil Deposit

#include <bits/stdc++.h>
using namespace std ;
typedef long long ll;
ll m,n;
char mp[][];
ll dir[][]= { {,},{-,},{-,},{-,-},{,-},{,-},{,},{,} };//方向可以任意,当前方向见图
void dfs(ll x,ll y)
{
mp[x][y]='*';//把当前的@转换成*,避免重复查找
for(ll i=; i<; i++)
{
ll xx=x+dir[i][],yy=y+dir[i][];
if(xx>=&&xx<=m&&yy>=&&yy<=n&&mp[xx][yy]=='@')
{
dfs(xx,yy);
}
}
return;//递归结束
}
int main()
{
while(~scanf("%lld%lld",&m,&n)&&n&&m)
{
ll sum=;
for(ll i=; i<=m; i++)
{
for(ll j=;j<=n;j++)
{
cin>>mp[i][j];
//scanf(" %c",&mp[i][j]);
//两种读入方式均可,要注意的是,用scanf()读入的话,需要在%c之前加入一个空格,这是专门用来吸收"\n"
}
}
for(ll i=; i<=m; i++)
{
for(ll j=; j<=n; j++)
{
if(mp[i][j]=='@')
{
dfs(i,j);
sum++;
}
}
}
cout<<sum<<endl;
}
}

Red and Black

用dfs搜索最长路,黑砖可走,红砖不可走,@表示出发点,输出最大黑砖数

#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
typedef long long ll;
ll m,n;
char mp[][];
ll dir[][]={ {-,},{,},{,-},{,} };
ll s;
void dfs(ll x,ll y)
{
ll xx,yy;
for(ll i=;i<;i++)
{
xx=x+dir[i][];
yy=y+dir[i][];
if(xx>=&&xx<=n&&yy>=&&yy<=m&&mp[xx][yy]!='#')
{
s++;
mp[xx][yy]='#';
dfs(xx,yy);
}
}
}
int main()
{
while(~scanf("%lld %lld",&m,&n)&&m&&n)
{
ll xx,yy;
for(ll i=;i<=n;i++)
{
for(ll j=;j<=m;j++)
{
scanf(" %c",&mp[i][j]);
if(mp[i][j]=='@')
{
xx=i;
yy=j;
}
}
}
s=;
mp[xx][yy]='#';
dfs(xx,yy);
cout<<s<<endl;
}
}

P1162 填涂颜色

建议从1开始读入,因为这样有一个好处,能够建立起天然的下标为0的围墙数组,可以防止数组下标小于0,以至于越界

dfs1

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e6+;
ll n;
ll mp[][];
ll vis[][];
ll dir[][]= { {-,},{,},{,-},{,} };
void dfs(ll x,ll y)
{
if(x==||y==||x>n||y>n)
return;
for(ll i=; i<; i++)
{
ll xx=x+dir[i][],yy=y+dir[i][];
if(mp[xx][yy]!=&&xx>=&&xx<=n&&yy>=&&yy<=n&&!vis[xx][yy])
{
vis[xx][yy]=;
dfs(xx,yy);
}
}
}
int main()
{
memset(vis,,sizeof vis);
memset(mp,,sizeof mp);
scanf("%lld",&n);
for(ll i=; i<=n; i++)
{
for(ll j=; j<=n; j++)
{
cin>>mp[i][j];
}
}
for(ll i=;i<=n;i++)
{
if(mp[][i]==)
dfs(,i);
if(mp[i][]==)
dfs(i,);
if(mp[n][i]==)
dfs(n,i);
if(mp[i][n]==)
dfs(i,n);
}
for(ll i=; i<=n; i++)
{
for(ll j=; j<=n; j++)
{
if(j>)
cout<<' ';
if(mp[i][j]!=&&!vis[i][j])
mp[i][j]=;
cout<<mp[i][j];
}
cout<<endl;
}
}

dfs2

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mp[][];
ll n;
ll dir[][]={ {-,},{,},{,-},{,} };
void dfs(ll x,ll y)
{
mp[x][y]=;
for(ll i=;i<;i++)
{
ll xx=x+dir[i][],yy=y+dir[i][];
if(xx>=&&yy>=&&xx<=n+&&yy<=n+&&mp[xx][yy]==)
{
dfs(xx,yy);
}
}
}
int main()
{
scanf("%lld",&n);
for(ll i=;i<=n;i++)
{
for(ll j=;j<=n;j++)
{
cin>>mp[i][j];
}
}
dfs(,);
for(ll i=;i<=n;i++)
{
for(ll j=;j<=n;j++)
{
if(j>)
{
cout<<' ';
}
if(mp[i][j]==)
{
mp[i][j]=;
}
else if(mp[i][j]==)
{
mp[i][j]=;
}
cout<<mp[i][j];
}
cout<<endl;
}
}

-------------------------------------------------------------------------------------------------------------

DFS【搜索1】的更多相关文章

  1. hdu 1312:Red and Black(DFS搜索,入门题)

    Red and Black Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  2. [ZOJ 1011] NTA (dfs搜索)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1011 题目大意:在一棵树上,给你起始状态,问你能否到达终止状态. ...

  3. HDU 1312:Red and Black(DFS搜索)

      HDU 1312:Red and Black Time Limit:1000MS     Memory Limit:30000KB     64bit IO Format:%I64d & ...

  4. hihocoder 1050 树中的最长路(动态规划,dfs搜索)

    hihocoder 1050 树中的最长路(动态规划,dfs搜索) Description 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中,小Ho发现他不仅 ...

  5. sdut 2152:Balloons(第一届山东省省赛原题,DFS搜索)

    Balloons Time Limit: 1000MS Memory limit: 65536K 题目描述 Both Saya and Kudo like balloons. One day, the ...

  6. 蓝桥杯 历届试题 剪格子(dfs搜索)

    历届试题 剪格子 时间限制:1.0s   内存限制:256.0MB 问题描述 如下图所示,3 x 3 的格子中填写了一些整数. +--*--+--+ |* || +--****--+ ||* | ** ...

  7. DFS搜索题素数环

    素数环: 输入整数1,2,3,4,5,···,n组成一个环,使得相邻两个整数之和均为素数. 输出时从整数1开始逆时针排列.同一个环应恰好输出一次.n<=16. Sample: input: 6 ...

  8. poj 3083 Children of the Candy Corn 【条件约束dfs搜索 + bfs搜索】【复习搜索题目一定要看这道题目】

    题目地址:http://poj.org/problem?id=3083 Sample Input 2 8 8 ######## #......# #.####.# #.####.# #.####.# ...

  9. codeforces 570 D. Tree Requests 树状数组+dfs搜索序

    链接:http://codeforces.com/problemset/problem/570/D D. Tree Requests time limit per test 2 seconds mem ...

  10. nyist oj 19 擅长排列的小明(dfs搜索+STL)

    擅长排列的小明 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描写叙述 小明十分聪明.并且十分擅长排列计算.比方给小明一个数字5,他能立马给出1-5按字典序的全排列,假设你想 ...

随机推荐

  1. springboot手动事务回滚

    亲测在使用@Transactional.@Transactional(rollbackFor = Exception.class)及catch异常之后 throw new RuntimeExcepti ...

  2. js获得url传过来的参数

     function  getParam(url) {                  var arr = url.split('?');   //取?以后                 var a ...

  3. Flutter + Android 混合开发

    JIT (Just In Time) 即时编译器, 边执行边编译 程序运行时,JIT 编译器选择将最频繁执行的方法编译成本地代码.运行时才进行本地代码编译而不是在程序运行前进行编译 AOT可以理解为“ ...

  4. web自动化 -- 框架

    一.框架源码 https://github.com/jiangnan27/Autotest_UI_Open   二.框架大概介绍 Python3 + selenium3 + pytest5.3 + a ...

  5. 手写IOC容器

    IOC(控制翻转)是程序设计的一种思想,其本质就是上端对象不能直接依赖于下端对象,要是依赖的话就要通过抽象来依赖.这是什么意思呢?意思就是上端对象如BLL层中,需要调用下端对象的DAL层时不能直接调用 ...

  6. yum下载软件包

    方法一: downloadonly插件有一个yum的插件叫做downloadonly,就是只下载不安装的意思.1. 安装插件yum install yum-download2. 下载yum updat ...

  7. 最长公共子序列dp入门

    #include <iostream> #include <string> #include <string.h> #include <vector> ...

  8. Seaborn基础2

    import matplotlib.pyplot as plt import seaborn as sns import numpy as np def sinplot(flip = 1): x = ...

  9. PHP date_get_last_errors() 函数

    ------------恢复内容开始------------ 实例 返回解析日期字符串时的警告和错误: <?phpdate_create("gyuiyiuyui%&&/ ...

  10. luogu P4525 自适应辛普森法1

    LINK:自适应辛普森法1 观察题目 这个东西 凭借我们的数学知识应该是化简不了的. 可以直接认为是一个函数 求定积分直接使用辛普森就行辣. 一种写法: double a,b,c,d; double ...