BFS
其实广度优先搜索就是利用了广度优先遍历的一种搜索算法。我个人总结的该算法包含以下几个关键点,掌握了这几个点,该算法也就掌握的很好了。下面也基本上是围绕这几个关键点展开的。
1.状态
2.状态转移方式
3.有效状态
4.队列
5.标记
迷宫问题
链接:http://poj.org/problem?id=3984
本题也是一个走迷宫的问题,但是本题和之前的几道题之间的差距就在于本题问你是如何走得,也就时你走迷宫的具体路径,主体思想跟之前的几道题没有变依然是bfs类的问题,但是重点是如何储存走过的点,以及如何输出。
记录输入输出的思想就是要从终点开始往回找点,用另外的结构体数组储存一下,然后输出就可以了,但是如何往回找呢?往回找就看你是如何储存的,先申请结构体数组。用要压入点的位置pre[tmp2.x][tmp2.y].x来记录前一个数组横坐标的位置,pre[tmp2.x][tmp2.y].y来记录另外一个数字纵坐标的位置。
pre[tmp2.x][tmp2.y].x = tmp1.x;
pre[tmp2.x][tmp2.y].y = tmp1.y;
#include<stdio.h>
#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
int maze[6][6];
int vis[6][6];
struct Point{
int x, y;
}tmp1, tmp2;
Point pre[10][10];
int mt[4][2] = {1,0,-1,0,0,1,0,-1};
queue<Point>q;
Point ans[30];
int main(){
int i, j;
while(~scanf("%d %d %d %d %d", &maze[0][0], &maze[0][1], &maze[0][2], &maze[0][3],&maze[0][4],&maze[0][5])){
for(i = 1; i < 5; i++){
for(j = 0; j < 5; j++){
scanf("%d", &maze[i][j]);
}
}
while(!q.empty()){
q.pop();
}
memset(vis, 0, sizeof(vis));
tmp1.x = 0;
tmp1.y = 0;
vis[0][0] = 1;
q.push(tmp1);
while(!q.empty()){
tmp1 = q.front();
q.pop();
for(i = 0; i < 4; i++){
tmp2.x = tmp1.x + mt[i][0];
tmp2.y = tmp1.y + mt[i][1];
if(tmp2.x >= 0 && tmp2.x < 5 && tmp2.y >= 0 && tmp2.y < 5 && !vis[tmp2.x][tmp2.y] && maze[tmp2.x][tmp2.y] == 0){
//约束条件
vis[tmp2.x][tmp2.y] = vis[tmp1.x][tmp1.y] + 1;
q.push(tmp2);
pre[tmp2.x][tmp2.y].x = tmp1.x;//保存前一个位置的横坐标
pre[tmp2.x][tmp2.y].y = tmp1.y;//保存前一个位置的纵坐标
}
}
if(vis[4][4])break;
}
//cout<<vis[4][4]<<endl;
int lastx = 4, lasty = 4;//终点的位置
int x, y, num = 0;
while(lastx || lasty){//如果lastx, lassty,如果全为零的话就停止
ans[num].x = lastx;//ans 来记录一下
ans[num++].y = lasty;
x = lastx;
y = lasty;
lastx = pre[x][y].x;//读取下一个,也就是之前保存的前一个
lasty = pre[x][y].y;
}
//cout<<num<<endl;
printf("(0, 0)\n");
for(i = num-1; i >= 0; i--){//逆序输出
printf("(%d, %d)\n", ans[i].x, ans[i].y);
}
}
return 0;
}
DFS
dfs基于递归思想,递归思想就是把一个事拆分成若干见相同的小事共同组合完成
理解深度优先算法的关键在于解决“当下该如何做”。至于下一步应该如何做,和当下应该如何做是一样的,对!就是用递归!自己调用自己!
关键:
void dfs(int step)
{
判断边界,如果到了边界当然直接返回啦
尝试每一种可能结果for(i=0;i<n;i++)
{
处理当前步
继续下一步dfs(step + 1)
}
返回
}
例题八皇后问题
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int hang[11], n=8;
int a[10][10] = { 0 };
int t = 1;
void print()
{
printf("No. %d\n", t++);
for (int i = 1; i <= 8; i++)
{
for (int j = 1; j <= 8; j++)
{
printf("%d ", a[j][i]);
}
printf("\n");
}
}
bool judge(int num)
{
for (int i = 1; i < num; i++)
if (hang[num] == hang[i] || abs(hang[i] - hang[num]) == num - i)
//判断列和对角线
return 0;
return 1;
}
void dfs(int num)
{
if (num >= 9){
print();
}
for (int i = 1; i <= 8; i++)
{
hang[num] = i;
if (a[num][i]!=1&&judge(num))
{
a[num][i] = 1;
dfs(num + 1);
a[num][i] = 0;
}
}
}
int main()
{
//freopen("1.txt", "w", stdout);
dfs(1);
return 0;
}
输出部分截图。