描述
dfs
从某点出发,沿着一个方向往下试探,当找到目标位置,还需回溯,以便找到所有路径,再比较
最短的路径,比较盲目,效率不高, 使用了栈
bfs
将队首结点可拓展的点入队,如果没有可拓展的点,将队首结点出队,重复以上步骤,
直到到达目标位置或者队列为空,得到路径一定是最短的, 使用了队列;
dfs代码
一维dfs
#include<cstdio>
#include<iostream>
using namespace std;
int a[10], book[10], to = 0;//装数, 标记
void dfs(int step)//表示站在第几个盒子面前
{
if(step == 9 + 1)//如果站在第十个盒子面前,那么前九个盒子已经放好扑克牌了
{
if(a[1]*100 + a[2]*10 + a[3] +a[4] *100+ a[5]*10 + a[6] == a[7]*100 + a[8]*10 + a[9])
{//相关判断条件, 满足要求就打印这个解
to++;
printf("%d%d%d + %d%d%d = %d%d%d\n", a[1], a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
}
return;//重要-----返回之前的一步
}
for(int i =1;i<=9;i++)// 现在是站在第step个盒子面前, 按照1.2.3....9的顺序一一尝试
{
if(book[i]==0)//判断是否被标记使用过, 为0表示还没有使用过
{
a[step] = i;//将i放入第step个盒子中
book[i] = 1;//标记已经使用过
dfs(step + 1);//继续下一步
book[i] = 0;//重要-----要将刚才尝试的收回, 才能进行下一步
}
}
}
int main()
{
dfs(1);//站在第一个盒子前
printf("总次数=%d\n", to/2);//有重复的
return 0;
}
二维dfs
#include<cstdio>//最短路径
#include<iostream>
using namespace std;//1为障碍物
int n, m,a[100][100],book[100][100], d[4][2] = {1,0,0,1,-1,0,0,-1};
int sx , sy , step = 0, ex, ey, mi=9999;
void dfs(int sx, int sy, int step)
{
if(sx==ex && sy ==ey)//等于终点了
{
if(step<mi)//找到最短路径
mi = step;
return;//返回上一步
}
for(int i=0;i<4;i++)
{
int tx = sx + d[i][1];//移动位置
int ty = sy + d[i][0];
if(tx < 1|| tx > n || ty <1 || ty >m)//越界了跳过
continue;
if(a[tx][ty]==0 && book[tx][ty] == 0)//如果不是障碍物,且没有标记过
{
book[tx][ty] = 1;//标记走过
dfs(tx, ty, step + 1);//开始尝试下一个点, 步数也增加
book[tx][ty] = 0;//尝试结束, 取消标记
}
}
return;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
cin>>sx>>sy>>ex>>ey;//起点 终点
dfs(sx, sy, step);
cout<<"step = "<<mi<<endl;
return 0;
}
bfs代码
二维bfs-
#include <iostream> /* 最短路径 */
#include <queue>
#include <map>
using namespace std;
int n,m,sx,sy,ex,ey;
int a[100][100], v[100][100], d[4][2] = {1,0,0,1,-1,0,0,-1};
struct po{
int x, y, f,s;//可放入各种条件
};
void bfs()
{
queue<po> r;//建队列
r.push({sx,sy});//把当前位置放进去
v[sx][sy] = 1;
while(r.size())//队列不为空时
{
int x = r.front().x;//取出队顶元素
int y = r.front().y;
if(x == ex && y == ey)//判断是否符合条件
{
cout<<r.front().s;
break;//符合跳出循环
}
for(int i=0;i<4;i++)
{
int tx = x + d[i][1];//继续移动位置
int ty = y + d[i][0];
if(tx < 1|| tx > n || ty < 1 || ty >m)//越界了跳过
continue;
if(a[tx][ty] == 0 && v[tx][ty] == 0)//如果没有走过, 且是空地
{
po temp;//临时变量存储位置,便于放入队列
temp.x = tx;
temp.y = ty;
temp.s = r.front().s + 1;//位置移动,步数加1
r.push(temp);
v[tx][ty] = 1;//标记移动过的位置
}
}
r.pop();//弹出位置
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
cin>>sx>>sy>>ex>>ey;
bfs();
return 0;
}
经典习题
全排列
#include <iostream>//全排列(有stl工具)
#include <vector>
using namespace std;
const int N = 15;
bool st[N];
int a[N];
vector<int> ve;
int v[N],n;
void dfs(int x)
{
if(x > n)
{
for(vector<int>::iterator it=ve.begin();it != ve.end();it++)
cout<<*it;
cout<<endl;
return;
}
for(int i=1;i<=n;i++)
{
if(v[i]) continue;
v[i]=1;
ve.push_back(a[i]);
dfs(x+1);
v[i]=0;
ve.pop_back();
}
}
int main(void){
scanf("%d", &n);
for(int i=1;i<=n;i++)
scanf("%d", &a[i]);
dfs(1);
return 0;
}
八皇后
#include<cstdio>
#include<iostream>
using namespace std;
int arr[14],v[3][28], ans = 0, n;
void dfs(int line){
if(line > n){
ans++;//几种方法
for(int i = 1;i <= n;i++)
cout << arr[i] << " ";
cout << endl;
return;
}
for(int i = 1;i <= n;i++){
if((!v[0][i]) && (!v[1][line+i]) && (!v[2][line-i+n])){
arr[line] = i;
v[0][i] = 1; v[1][line+i] = 1; v[2][line-i+n] = 1;
dfs(line+1);
v[0][i] = 0; v[1][line+i] = 0; v[2][line-i+n] = 0;
}
}
}
int main(){
cin >> n;
dfs(1);
if(ans == 0)
cout<<"no solute!"<<endl;
return 0;
}