DFS专题(入门,经典为主)
2018-01-15 16:54
155 查看
接触了图论以后,我才发现搜索原来是那么的简单。由于最近刘老师给我们讲的图论题实在是不太能够消化,于是我就转向了搜索那一块,从此与搜索过上了幸福美好的生活。
最近突然才发现,搜索其实还是挺简单的。以前培训的时候,最害怕的就是搜索了,感觉完全听不懂。然而,现在随便翻一下黑皮书就明白了,我也不知道究竟是为什么。学会搜索后,就又有了一大波水题哈哈哈。
因为深搜题我已经刷了2个大周了,便觉得特别亲切,就先讲几道深搜题吧!
华丽丽的分割线
第一题:细胞问题
这是一道非常典型的题,在一个二维数组中进行深度优先搜索,开一个方向数组,想上下左右四个方向进行搜索。
#include<bits/stdc++.h>
using namespace std;
int n,k,m,ans=0;
char a[200][200];
int dx[5]={-1,1,0,0};
int dy[5]={0,0,-1,1}; //方向数组
inline void into() //输入
{
cin>>m>>n;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++) cin>>a[i][j];
}
void dfs(int x,int y) //深搜
{
for(int i=0;i<4;i++) //朝四个方向进行搜索
{
int xx=x+dx[i],yy=y+dy[i];
if(a[xx][yy]!='0')
{
a[xx][yy]='0';
dfs(xx,yy);
}
}
}
int main()
{
memset(a,'0',sizeof(a));
into();
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
if (a[i][j]!='0')
{
ans++;
a[i][j]='0';
dfs(i,j);
}
cout<<ans;
return 0;
} 第二题:迷宫
这道题也算是非常典型了,与上一道题差不多,只是多加了一个回溯罢了。不多说了,代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,m,t,sx,sy,fx,fy,x,y,ans=0;
bool a[100][100];
int dx[5]={-1,1,0,0};
int dy[5]={0,0,-1,1}; //方向数组,仍然是上下左右四个方向
void dfs(int x,int y) //深搜
{
if (x==fx&&y==fy) //如果到达终点,方案数加一,跳出
{
ans++;
return;
}
a[x][y]=false; //这样就能够不让往回走
for(int i=0;i<4;i++)
{
int xx=x+dx[i],yy=y+dy[i];
if (a[xx][yy]==true) dfs(xx,yy);
}
a[x][y]=true; //回溯
}
int main()
{
memset(a,false,sizeof(a)); //边界先为假
cin>>n>>m>>t;
cin>>sx>>sy>>fx>>fy;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) a[i][j]=true;
for (int i=1;i<=t;i++) //不能走的地方也置为假
{
cin>>x>>y;
a[x][y]=false;
}
dfs(sx,sy);
cout<<ans;
return 0;
}
刷完了两道经典题,感觉信心满满,下面就来一道更经典的题吧,这是我曾经的噩梦,就来详细的说一下吧。
八皇后:
相信这一道题大家肯定都不陌生,至少对于学过搜索,接触过搜索的同学们,这是一道必刷的题。这道题教上面,稍微难了一点,不过还是花了我10分钟左右。
题目描述:(无)大致就是在n*n的棋盘内放置皇后,使他们不能再同一行,同一列,同一斜排。代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,k,s=0;
bool a[300]={},b[1000]={},c[1000]={}; //a是竖排的,b和c分别是斜排的
void dfs(int k) //深搜
{
if(k-1==n) //如果放满了,方案数加一,跳出
{
s++;
return;
}
for(int i=1;i<=n;i++) //放n个皇后
{
if(a[i]==false&&b[i-k+100]==false&&c[i+k]==false) //分别判断竖排和斜排是否会造成攻击,不加100会变负数
{
a[i]=true;
b[i-k+100]=true;
c[i+k]=true;
dfs(k+1);
a[i]=false; //一大堆回溯
b[i-k+100]=false;
c[i+k]=false;
}
}
}
int main()
{
cin>>n;
dfs(1);
cout<<s;
return 0;
} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~又一道华丽丽的分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
写完了题解,感觉特别开心,果然有代码博客写的就是快哈哈哈哈。那么就告一段落了。
最近突然才发现,搜索其实还是挺简单的。以前培训的时候,最害怕的就是搜索了,感觉完全听不懂。然而,现在随便翻一下黑皮书就明白了,我也不知道究竟是为什么。学会搜索后,就又有了一大波水题哈哈哈。
因为深搜题我已经刷了2个大周了,便觉得特别亲切,就先讲几道深搜题吧!
华丽丽的分割线
第一题:细胞问题
这是一道非常典型的题,在一个二维数组中进行深度优先搜索,开一个方向数组,想上下左右四个方向进行搜索。
#include<bits/stdc++.h>
using namespace std;
int n,k,m,ans=0;
char a[200][200];
int dx[5]={-1,1,0,0};
int dy[5]={0,0,-1,1}; //方向数组
inline void into() //输入
{
cin>>m>>n;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++) cin>>a[i][j];
}
void dfs(int x,int y) //深搜
{
for(int i=0;i<4;i++) //朝四个方向进行搜索
{
int xx=x+dx[i],yy=y+dy[i];
if(a[xx][yy]!='0')
{
a[xx][yy]='0';
dfs(xx,yy);
}
}
}
int main()
{
memset(a,'0',sizeof(a));
into();
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
if (a[i][j]!='0')
{
ans++;
a[i][j]='0';
dfs(i,j);
}
cout<<ans;
return 0;
} 第二题:迷宫
这道题也算是非常典型了,与上一道题差不多,只是多加了一个回溯罢了。不多说了,代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,m,t,sx,sy,fx,fy,x,y,ans=0;
bool a[100][100];
int dx[5]={-1,1,0,0};
int dy[5]={0,0,-1,1}; //方向数组,仍然是上下左右四个方向
void dfs(int x,int y) //深搜
{
if (x==fx&&y==fy) //如果到达终点,方案数加一,跳出
{
ans++;
return;
}
a[x][y]=false; //这样就能够不让往回走
for(int i=0;i<4;i++)
{
int xx=x+dx[i],yy=y+dy[i];
if (a[xx][yy]==true) dfs(xx,yy);
}
a[x][y]=true; //回溯
}
int main()
{
memset(a,false,sizeof(a)); //边界先为假
cin>>n>>m>>t;
cin>>sx>>sy>>fx>>fy;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) a[i][j]=true;
for (int i=1;i<=t;i++) //不能走的地方也置为假
{
cin>>x>>y;
a[x][y]=false;
}
dfs(sx,sy);
cout<<ans;
return 0;
}
刷完了两道经典题,感觉信心满满,下面就来一道更经典的题吧,这是我曾经的噩梦,就来详细的说一下吧。
八皇后:
相信这一道题大家肯定都不陌生,至少对于学过搜索,接触过搜索的同学们,这是一道必刷的题。这道题教上面,稍微难了一点,不过还是花了我10分钟左右。
题目描述:(无)大致就是在n*n的棋盘内放置皇后,使他们不能再同一行,同一列,同一斜排。代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,k,s=0;
bool a[300]={},b[1000]={},c[1000]={}; //a是竖排的,b和c分别是斜排的
void dfs(int k) //深搜
{
if(k-1==n) //如果放满了,方案数加一,跳出
{
s++;
return;
}
for(int i=1;i<=n;i++) //放n个皇后
{
if(a[i]==false&&b[i-k+100]==false&&c[i+k]==false) //分别判断竖排和斜排是否会造成攻击,不加100会变负数
{
a[i]=true;
b[i-k+100]=true;
c[i+k]=true;
dfs(k+1);
a[i]=false; //一大堆回溯
b[i-k+100]=false;
c[i+k]=false;
}
}
}
int main()
{
cin>>n;
dfs(1);
cout<<s;
return 0;
} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~又一道华丽丽的分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
写完了题解,感觉特别开心,果然有代码博客写的就是快哈哈哈哈。那么就告一段落了。
相关文章推荐
- hdu 1241 Oil Deposits (dfs经典入门)
- UVA 572&& PoJ2386 两道DFS入门最经典的题目
- poj入门水题--深度搜索(dfs)题 1011,含各种剪枝,比较经典
- 搜索入门之dfs--经典的迷宫问题解析
- CUGB专题训练之数据结构:E - Keywords Search(HDU 2222 AC自动机经典入门模板题)
- 【搜索入门专题练习1】hdu1241+hdu1312 C+D【DFS】
- DFS-BFS搜索专题【经典训练题】【有时间一个个做下来】
- 入门经典-习题7-1,109-uva208消防车-DFS,并查集,打印路径,利用set保存边,字典序,STL⭐⭐⭐⭐⭐复杂度:3
- hdu1016枚举递归-经典DFS-简单回溯入门
- [MVVM专题]__又见经典入门示例
- DFS-BFS搜索专题【经典训练题】【有时间一个个做下来】
- [MVVM专题]__又见经典入门示例
- HDU 1312 Red and Black DFS入门经典例题
- STL + c++ + 模板 + 重要思维 + 基础算法+ 经典算法 + 经典实例 + 编程总结+ 心得+ 入门必会 + 知识点汇总。+string +dfs +bfs等重要算法
- 【Android】【笔记】《Android 入门经典》part 10 数据存储
- windows 网络编程经典入门
- hdu1241(DFS入门)
- c++学习笔记(17.专题四经典问题解析)
- 算法竞赛入门经典-第二章源代码
- 算法竞赛入门经典 程序3-2 开灯问题