这几天刷了点bfs与dfs的题,来总结下,
上~~~~上图
咳~咳~咳 错了。。。。。
好了,好了,咋也是正经人,进入主题
dfs实叫深度优先搜索算法,起始它只是一种搜索的方法思路,并没有固定的算法格式,假设这样的情景,一个姑娘爱你爱的深沉,被你拒绝了好多次了,可就是不放弃你说“只要你没有结婚,我就有机会”,典型的不撞南墙不回头,一条道走到黑,这种。。。。对,就是这样的,dfs就是有着你追隔壁班女神的这样的执着,说到这里,继续上图。。。。
假设你穿越到古代的你娶了三位小妾,晚上让谁来侍寝苦恼了你好久,你需要一个他们侍寝的顺序
1号小姐姐 2号小姐姐 3号小姐姐
跟随着红色箭头你就可以得到3位美妾的侍寝的所有可能的顺序了,我就问你你选哪种,我选三在最后一夜的,别问我为什么,就因为有句话叫先苦后甜~ 嘻嘻嘻。DFS的重要点在于状态回溯。代码如下
#include
#include
using namespace std;
int n;
const int N =8;
int path[N];
bool st[N];
void dfs(int x){
if(x==n){
for(int i=0;i>n;
dfs(0);
return 0;
}
POJ 1321-棋盘问题
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
input :
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
output: 2
1
你会发现核心代码跟上述太大的没有区别,只是我们需要确定节点是“#”才可加入递归中去
#include
#include
#include
using namespace std;
int n,k,l;
int flag;
const int N =10;
char g[N][N];
bool col[N];
void dfs(int x,int t){
if(t==k){
flag++;
return ;
}
if(x==n) return ;
//不摆放
dfs(x+1,t);
//摆放
for(int i=0;i>g[i][j];
}
dfs(0,0);
printf("%d\n",flag);
}
return 0;
}
假设有如上图1这样的迷宫,0为可走,1为墙(别想狗急跳墙了哈),只有上下左右四个方向我们可以走,我们模拟下用bfs如何从左上角到达右下角的路径的,我们从(0,0)点出发,向周围扩展
只有(1,0),从(1,0)这个点再扩展到(2,0),(1,1)下次扩展只有(1,1)可以扩展,扩展到(1,2),从(1,2)就可扩展到(2,2)这时遍历完了。由于每次都是向周围扩展一次,最先到达的不就是我们需要的最短的路径了,这里需要借用数据结构了
int n = 10, m = 10; //地图宽高
void BFS()
{
queue que; //用队列来保存路口
int graph[n][m]; //地图
int px[] = {-1, 0, 1, 0}; //移动方向的数组
int py[] = {0, -1, 0, 1};
que.push(起点入队); //将起点入队
while (!que.empty()) { //只要队列不为空
auto temp = que.pop(); //得到队列中的元素
for (int i = 0; i != 4; ++i) {
if(//可以走) {
//标记当前格子
//将当前状态入队列,等待下次提取
}
}
}
}
bfs裸题,给定一个 n×m 的二维整数数组,用来表示一个迷宫,数组中只包含 00 或 11,其中 00 表示可以走的路,11 表示不可通过的墙壁。
最初,有一个人位于左上角 (1,1) 处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。
请问,该人从左上角移动至右下角 (n,m) 处,至少需要移动多少次。
#include
#include
#include
using namespace std;
const int N = 100;
typedef pairPII;
int n,m;
int g[N][N];
int d[N][N];//记录到达这个点行走的路程,
PII h[N*N];//数组模拟的队列
int tx[4]={0,1,0,-1};
int ty[4]={1,0,-1,0};
int bfs(){
int hh=0,tt=0;
memset(d,-1,sizeof(d));//初始为-1,也可以区别当前的节点有没有走过
h[tt]={0,0};
d[0][0]=0;
while(tt>=hh){
auto t=h[hh++];//出队
for(int i=0;i<4;i++){
int x=t.first+tx[i],y=t.second+ty[i];
if(x>=0&&x=0&&y>n>>m;
for(int i=0;i>g[i][j];
cout<
农夫约翰已被告知一头逃亡母牛的位置,并希望立即抓住她。他从数轴上的点N (0 ≤ N ≤ 100,000) 开始,而奶牛在同一数轴上的点K (0 ≤ K ≤ 100,000) 处。Farmer John 有两种交通方式:步行和传送。
* 行走:FJ 可以在一分钟内从X点移动到X - 1 或X + 1点
* 传送:FJ 可以在一分钟内从X点移动到 2 × X点。
如果母牛不知道它的追逐,根本不动,农夫约翰需要多长时间才能取回它?
input :5 17
output: 4
Farmer John 到达逃亡母牛的最快方式是沿着以下路径移动:5-10-9-18-17,需要 4 分钟。
#include
#include
#include
#include
using namespace std;
struct node{
int x,td;
};
const int N = 100010;
bool map[N];
int n,m;
bool check(int x){
if(x<0||x>N||map[x])return false;
return true;
}
int bfs(){
queueq;
node t={n,0};
q.push(t);
map[n]=true;
while(q.size()){
node temp=q.front();
q.pop();
if(temp.x==m)return temp.td;
//状态转移
if(check(temp.x-1)){
node e={temp.x-1,temp.td+1};
map[e.x]=true;
q.push(e);
}
if(check(temp.x+1)){
node e={temp.x+1,temp.td+1};
map[e.x]=true;
q.push(e);
}
if(check(temp.x*2)){
node e = {temp.x*2,temp.td+1};
map[e.x]=true;
q.push(e);
}
}
}
int main(){
while(~scanf("%d%d",&n,&m)){
memset(map,false,sizeof(map));
int ans=bfs();
printf("%d\n",ans);
}
}
对于这两个搜索方法,其实我们是可以轻松的看出来,他们有许多差异与许多相同点的。
1.数据结构上的运用
DFS用递归的形式,用到了栈结构,先进后出。
BFS选取状态用队列的形式,先进先出。
2.复杂度
DFS的复杂度与BFS的复杂度大体一致,不同之处在于遍历的方式与对于问题的解决出发点不同,DFS适合目标明确,而BFS适合大范围的寻找。
3.思想
思想上来说这两种方法都是穷竭列举所有的情况。
喔噻,看到这里了,可惜没有图可以上了,不然奖励奖励,哈哈哈