DFS模板

题型分类:
我们可以将DFS题分为两大类:
1 . 地图型:这种题型将地图输入,要求完成一定的任务。因为地图的存在。使得题意清楚形象化,容易理清搜索思路。
AOJ 869-迷宫(遍历地图,四向搜索)
HDU 1035-Robot Motion(指定方向搜索,迷路(循环)判断)
HDU 1045-Fire Net(check函数,回溯)
HDU 1010-Tempter of the Bone(奇偶剪枝,回溯)
2 . 数据型:这种题型没有给定地图,一般是一串数字或字母,要求按照一定的任务解题。相对于地图型,这种题型较为抽象,需要在数据中进行搜索。数据以数组的形式存储,那么只要将数组也当作一张图来进行搜索就可以了。
HDU 1016-Prime Ring Problem(回溯、素数筛)
HDU 1258-Sum It Up(双重DFS递归,去重技巧)
HDU 1015-Safecraker(回溯,字符处理)
HDU 2676-Sudoku(抽象,回溯)

核心思想:

void dfs()//参数用来表示状态
{
if(到达终点状态)
{
...//根据题意添加
return;
}
if(越界或者是不合法状态)
return;
if(特殊状态)//剪枝
return ;
for(扩展方式)
{
if(扩展方式所达到状态合法)
{
修改操作;//根据题意来添加
标记;
dfs();
(还原标记);
//是否还原标记根据题意
//如果加上(还原标记)就是 回溯法
} }
}

迷宫(一)

一天蒜头君掉进了一个迷宫里面,蒜头君想逃出去,可怜的蒜头君连迷宫是否有能逃出去的路都不知道。

看在蒜头君这么可怜的份上,就请聪明的你告诉蒜头君是否有可以逃出去的路。

输入格式

第一行输入两个整数 n 和 m,表示这是一个n×m 的迷宫。

接下来的输入一个 n 行m 列的迷宫。其中 'S' 表示蒜头君的位置,'*'表示墙,蒜头君无法通过,'.'表示路,蒜头君可以通过'.'移动,'T'表示迷宫的出口(蒜头君每次只能移动到四个与他相邻的位置——上,下,左,右)。

输出格式

输出一个字符串,如果蒜头君可以逃出迷宫输出"yes",否则输出"no"。

数据范围

1≤n,m≤10。

样例输入1

3 4

S**.

..*.

***T

样例输出1

no

样例输入2

3 4

S**.

....

***T

样例输出2

Yes

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int n,m;
char maps[15][15];
int vis[15][15];
int flag=0;
int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
//判断路是否能走
bool check(int x,int y){
return x>=1&&x<=n&&y>=1&&y<=m&&maps[x][y]!='*'&&vis[x][y]==0;
}
void dfs(int x,int y){
//终点就退出
if(maps[x][y]=='T'){
flag=1;
return ;
}
if(!check(x,y)) return ;
vis[x][y]=1;
for(int i=0;i<4;i++){
int newx=x+dir[i][0];
int newy=y+dir[i][1];
dfs(newx,newy);
}
return ;
}
int main()
{
int start,starty;
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>maps[i][j];
if(maps[i][j]=='S'){
start=i;
starty=j;
}
}
}
dfs(start,starty);
if(flag==1)
cout<<"yes"<<endl;
else
cout<<"no"<<endl;
}

hdu 1035 Robot Motion

问题描述

机器人已被编程为遵循其路径中的指令。网格中放置了机器人下一步移动方向的说明。可能的指令为

N北(在页面上方)

S南(在页面下方)

E东(在页面右侧)

W西(在页面左侧)

例如,假设机器人从北(顶部)启动网格1的一侧),并向南(向下)开始。显示了机器人遵循的路径。机器人在离开网格之前会先通过网格中的10条指令。

比较Grid 2中发生的情况,机器人仅执行3条指令一次,然后通过8条指令开始循环,并且永不退出。

您将编写一个程序,该程序确定机器人离开网格需要多长时间或机器人如何循环。

输入值

将有一个或多个网格供机器人导航。每个数据的格式如下。在第一行上,三个整数用空格隔开:网格中的行数,网格中的列数以及机器人从北方进入的列数。

可能的输入列从左侧的一开始编号。然后出现方向指示的行。每个网格将具有至少一个且最多10个行和列的指令。指令行仅包含字符N,S,E或W,没有空格。

输入的结尾由包含0 0 0的行指示。

输出量

对于输入中的每个网格,只有一行输出。机器人要么遵循一定数量的指令,然后从四个侧面中的任一侧退出网格,要么机器人一次遵循一定数量位置上的指令,

然后重复遵循一定数量位置上的指令。下面的示例输入对应于上面的两个网格,并说明了两种输出形式。单词“ step”总是紧随其后的是“(s)”,无论之前的数字是否为1。

样本输入

3 6 5 NEESWE WWWESS SNWWWW 4 5 1 SESWE EESNW NWEEN EWSEN 0 0

样本输出

10个步骤可在8个步骤的循环之前退出3个步骤

#include<iostream>
#include<bits/stdc++.h>
using namespace std; char maps[15][15];
int sum,m,n,s,flag,mark,mark_x,mark_y,vis[15][15];
void dfs(int x,int y,int ant){
if(x<0||y<0||x==m||y==n){//如果出界 就证明能够出去了
sum=ant;
return ;
}
if(vis[x][y]){//自身成环 记录目前的步数和坐标
flag=1;
mark_x=x,mark_y=y;
mark=ant;
return ;
}
vis[x][y]=ant+1;
if(maps[x][y]=='W'&&!sum&&!flag)
dfs(x,y-1,++ant);
if(maps[x][y]=='E'&&!sum&&!flag)
dfs(x,y+1,++ant);
if(maps[x][y]=='N'&&!sum&&!flag)
dfs(x-1,y,++ant);
if(maps[x][y]=='S'&&!sum&&!flag)
dfs(x+1,y,++ant);
}
int main(){
while(true)
{
cin>>m>>n;
if(m==0||n==0)
break;
cin>>s;
for(int i=0;i<m;i++)
cin>>maps[i];
sum=flag=0;
memset(vis,0,sizeof(vis));
dfs(0,s-1,0);
if(!flag)
cout<<sum<<" step(s) to exit"<<endl;
else
cout<<vis[mark_x][mark_y]-1<<" step(s) before a loop of "<<mark-vis[mark_x][mark_y]+1<<" step(s)"<<endl;
}
}

Tempter of the Bone

小狗在一个古老的迷宫中发现了一根骨头,这使他非常着迷。但是,当他捡起它时,迷宫开始摇晃,小狗可以感觉到地面下沉。他意识到骨头是一个陷阱,

他拼命试图摆脱这个迷宫。迷宫是一个矩形,大小为N×M。迷宫中有一扇门。刚开始时,门是关闭的,它将在第T秒打开一小段时间(少于1秒)。

因此,小狗必须在第T秒精确到达门。每秒钟,他可以将一个块移动到上,下,左和右相邻的块之一。一旦他进入一个街区,该街区的地面将开始下沉并在下一秒消失。

他不能在一个街区停留超过一秒钟,也不能搬到一个拜访的街区。可怜的小狗可以生存吗?请帮助他。

输入值

输入包含多个测试用例。每个测试用例的第一行包含三个整数N,M和T(1 <N,M <7; 0 <T <50),分别表示迷宫的大小和门打开的时间。 。接下来的N行给出迷宫的布局,每行包含M个字符。字符是以下之一:

‘X’: a block of wall, which the doggie cannot enter;

‘S’: the start point of the doggie;

‘D’: the Door; or

‘.’: an empty block.

输入以三个0终止。该测试用例将不被处理。

输出

对于每个测试用例,如果小狗可以存活,则在一行中打印“YES”,否则打印为“NO”。

样例输入:

4 4 5

S.X.

..X.

..XD

....

3 4 5

S.X.

..X.

...D

0 0 0

样例输出:

NO

YES

奇偶剪枝

把矩阵看成如下形式: 
0 1 0 1 0 1 
1 0 1 0 1 0 
0 1 0 1 0 1 
1 0 1 0 1 0 
0 1 0 1 0 1 
从为 0 的格子走一步,必然走向为 1 的格子 。
从为 1 的格子走一步,必然走向为 0 的格子 。
即: 
从 0 走向 1 必然是奇数步,从 0 走向 0 必然是偶数步。

所以当遇到从 0 走向 0 但是要求时间是奇数的或者 从 1 走向 0 但是要求时间是偶数的,都可以直接判断不可达!

#include<iostream>
#include<bits/stdc++.h>
using namespace std; int n,m,t,escape;
int dx,dy,sx,sy;
char maps[15][15];
int dir[4][2] = {{1,0}, {-1,0}, {0,1}, {0,-1}}; //上下左右4个方向
void dfs(int sx,int sy,int cnt){
int tmp;
//不满足要求超过地图范围
if(sx>n||sx<1||sy>m||sy>m||sy<1){
return;
}
//完成条件
if(sx==dx&&sy==dy&&cnt==t){
escape=1;
return;
}
if(escape) return;
//T−k−f<0
tmp=(t-cnt)-abs(sx-dx)-abs(sy-dy);
if(tmp<0||tmp&1)return;
for(int i=0; i<4; i++ ){
int newx = sx+dir[i][0];
int newy = sy+dir[i][1];
if( maps[newx ][ newy ] != 'X'){
maps[ newx ][ newy ] = 'X';
dfs(newx, newy, cnt+1);
maps[ newx ][newy ] = '.';
}
}
return;
}
int main(){
while (scanf("%d %d %d",&n,&m,&t)&&(m+n+t)){
int wall=0;
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
cin>>maps[i][j];
if(maps[i][j]=='S') {
sx=i;
sy=j;
}
else if( maps[i][j]=='D' ) {
dx=i;
dy=j;
}
else if( maps[i][j]=='X' )
wall++;
}
}
if( n*m-wall <= t ){
cout << "NO" << endl;
continue;
}
escape = 0;
maps[sx][sy] = 'X';
dfs(sx,sy,0);
if( escape )
cout << "YES" << endl;
else
cout << "NO" << endl;
}
}

HDU 1016-Prime Ring Problem

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int n;
int a[123],used[123];
int ok(int n){
int i;
for(i=2;i<n;i++){
if(n%i==0) return 0;
}
return 1;//素数
}
void dfs(int x){
int i;
if(x==n){
int j;
if(ok(1+a[x-1])==1){ //头尾和判断
cout<<"1";
for(j=1;j<n;j++) cout<<" "<<a[j]; //构造够n个了 输出数组。
cout<<endl;
return ;
}
}
for(i=2;i<=n;i++){
if(used[i]==0&&ok(i+a[x-1])==1) { //加上判断和是不是素数
a[x]=i;
used[i]=1; //标记使用了
dfs(x+1); //对第x+1个进行构造
used[i]=0; //标记复原
}
}
return ;
}
int main(){
int cas=1;
while(scanf("%d",&n)!=-1){
memset(used,0,sizeof(used)); // 赋值都没被使用过。
used[1]=1;
a[0]=1;
printf("Case %d:\n",cas++);
dfs(1); //从第1个数开始构造,因为以1开始
cout<<endl;
}
return 0;
}

DFS模板的更多相关文章

  1. BFS与DFS模板

    搜索问题的解法 DFS(深度优先搜索) BFS(广度优先搜索) backtracking(回溯) DFS模板 void dfs(...) { // 结束递归的条件 if (...) { ..... / ...

  2. BFS DFS模板

    转载于https://blog.csdn.net/alalalalalqp/article/details/9155419 BFS模板: #include<cstdio> #include ...

  3. 匈牙利算法dfs模板 [二分图][二分图最大匹配]

    最近学了二分图最大匹配,bfs模板却死活打不出来?我可能学了假的bfs 于是用到了dfs模板 寻找二分图最大匹配的算法是匈牙利算法 匈牙利算法的主要程序是寻找增广路 寻找增光路是过程是:从一个未经配对 ...

  4. POJ 1655.Balancing Act-树的重心(DFS) 模板(vector存图)

    Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17497   Accepted: 7398 De ...

  5. 二分图最大匹配(匈牙利算法Dfs模板)

    #include<iostream> #include<cstdio> #include<cstring> #define maxn 2020 using name ...

  6. hdu 1241Oil Deposits(dfs模板)

    题目链接—— http://acm.hdu.edu.cn/showproblem.php?pid=1241 首先给出一个n*m的字符矩阵,‘*’表示空地,‘@’表示油井.问在这个矩阵中有多少组油井区? ...

  7. dfs模板(真心不会深搜)

    栈 #include <stdio.h> #include <string.h> ][]; ][]; ,-, , }; , ,-, }; int Min; void dfs(i ...

  8. luogu P1238 走迷宫--DFS模板好(水)题

    题目描述 有一个m*n格的迷宫(表示有m行.n列),其中有可走的也有不可走的,如果用1表示可以走,0表示不可以走,文件读入这m*n个数据和起始点.结束点(起始点和结束点都是用两个数据来描述的,分别表示 ...

  9. 几种常见的dfs模板

    判断从v出发是否能走到终点 bool dfs(v){ if(v is 终点)return true; if(v is 旧点)return false; 将v标记为旧点: 对和v相邻的每个节点u{ if ...

随机推荐

  1. 建立局域网内使用的CentOS7-OpenStack源

    by 无若 1. 先建立局域网内使用的CentOS7源 这个参看 http://www.cnblogs.com/gleaners/p/5735472.html 2. 抓取所有OpenStack的包,文 ...

  2. 关于stm32 HardFault_Handler 异常的处理 死机

    在系统开发的时候,出现了HardFault_Handler硬件异常,也就是死机,尤其是对于调用了os的一系统,程序量大,检测堆栈溢出,以及数组溢出等,找了半天发现什么都没有的情况下,估计想死的心都有了 ...

  3. 批量删除gmail邮件

    以删除tor.com发送的邮件为例说明. 首先点击邮件搜索框右边的三角,在"发件人"下面写上"tor.com": 点"搜索"按钮,看一下范围 ...

  4. 【笔记】求数据的对应主成分PCA(第一主成分)

    求数据的第一主成分 (在notebook中) 将包加载好,再创建出一个虚拟的测试用例,生成的X有两个特征,特征一为0到100之间随机分布,共一百个样本,对于特征二,其和特征一有一个基本的线性关系(为什 ...

  5. Java调用Zookeeper

    watch机制 Zookeeper watch是一种监听通知机制,可以随时监听一些数据的变化,从而实现数据的及时性. Zookeeper所有的读操作getData(), getChildren()和 ...

  6. 安鸾CTF Writeup SSRF02

    SSRF02 题目链接:http://www.whalwl.host:8090/ 看到题目,以为是SSRF 获取内网信息, SFTP FTP Dict gopher TFTP file ldap 协议 ...

  7. STM32—重定向printf和getchar函数到串口

    在STM32测试串口的时候经常需要在开发板和上位机之间传输数据,我们可以用c语言中的printf()函数和getchar()函数来简化传输. 以printf()为例: printf()函数实际上是一个 ...

  8. AQS源码分析看这一篇就够了

      好了,我们来开始今天的内容,首先我们来看下AQS是什么,全称是 AbstractQueuedSynchronizer 翻译过来就是[抽象队列同步]对吧.通过名字我们也能看出这是个抽象类 而且里面定 ...

  9. 关于Ajax异步提交登录及增删改查小项目制作-登录

    一.登录的完成 先导包jquery和MySql //异步提交 <script type="text/javascript" src="js/jquery-1.8.2 ...

  10. FPGA学习过程(二)

    项目:数码管动态显示时间 首先建立一个计时一秒的模块,作为数码管显示的需要 module timer_s( input wire clk, input wire rst_n, output wire ...