BFS(宽搜)
预备知识
队列
常见操作
- 判断队列是否为空 q.empty()
- push
- pop
宽度优先搜索
二叉树的层次遍历
- 把当前点后面的所有点结构体加入队列中
- 最早扩展到的就是最短路径
- 记录最开始的坐标和结束的坐标
模板题 ACWing1101. 献给阿尔吉侬的花束
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 200 + 10;
char maze[maxn][maxn];
int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int t;
int r, c;
int start_x, start_y;
int end_x, end_y;
struct Node
{
int x;
int y;
int step;
}node[maxn * maxn];
bool check(int x, int y)
{
if (x >= 0 && x < r && y >= 0 && y < c) return true;
return false;
}
int bfs(int x, int y, int a, int b)
{
maze[x][y] = '#';
queue<Node> q;
Node start = {x, y, 0};
q.push(start);
while (!q.empty())
{
Node now = q.front();
q.pop();
if (now.x == a && now.y == b) return now.step;
for (int i = 0; i < 4; i ++ )
{
int dx = now.x + dir[i][0];
int dy = now.y + dir[i][1];
if (maze[dx][dy] != '#' && check(dx, dy))
{
Node ne = {dx, dy, now.step + 1};
maze[dx][dy] = '#'; // 不走回头路
q.push(ne);
}
}
}
return -1;
}
int main()
{
cin >> t;
while (t--)
{
cin >> r >> c;
memset(maze, 0, sizeof(maze));
for (int i = 0; i < r; i ++ ) scanf("%s", maze[i]);
for (int i = 0; i < r; i ++ )
{
for (int j = 0; j < c; j ++ )
{
if (maze[i][j] == 'S')
{
start_x = i;
start_y = j;
}
if (maze[i][j] == 'E')
{
end_x = i;
end_y = j;
}
}
}
int res = bfs(start_x, start_y, end_x, end_y);
if (res != -1) cout << res << endl;
else cout << "oop!" << endl;
}
}
hdoj 1495非常可乐
有几个问题解决不了:
- 怎么判断现在是处于哪个杯子
- 怎么判断它用了这个杯子
二维就够了,因为加起来是固定的。这里指的是我们自己创建的三维判断矩阵
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int v[5];
int sign[110][110][100];
struct cup //记录遍历中3个水杯容藏可乐情况
{
int v[5];
int step;
} temp;
void pour(int a, int b) //倒水函数,把a杯子中的可乐倒到b杯子中
{
int sum = temp.v[a] + temp.v[b];
if (sum >= v[b])
temp.v[b] = v[b];
else
temp.v[b] = sum;
temp.v[a] = sum - temp.v[b];
}
void bfs()
{
int i, j;
queue<cup> q;
cup cnt;
cnt.v[1] = v[1];
cnt.v[2] = 0;
cnt.v[3] = 0;
cnt.step = 0;
q.push(cnt);
memset(sign, 0, sizeof(sign));
sign[v[1]][0][0] = 1;
while (!q.empty())
{
cnt = q.front();
q.pop();
if (cnt.v[1] == cnt.v[3] && cnt.v[2] == 0)
{
printf("%d\n", cnt.step);
return;
}
for (i = 1; i < 4; ++i)
{
for (j = 1; j < 4; ++j)
{
if (i != j) //自己不倒水给自己
{
temp = cnt; //每个水位情况都要把所有操作枚举一遍,所以都要赋值为原始水位情况
pour(i, j);
if (!sign[temp.v[1]][temp.v[2]][temp.v[3]])
{
temp.step++;
q.push(temp);
sign[temp.v[1]][temp.v[2]][temp.v[3]] = 1;
}
}
}
}
}
printf("NO\n");
}
int main()
{
while (scanf("%d%d%d", &v[1], &v[2], &v[3]) && v[1] || v[2] || v[3])
{
if (v[2] > v[3])
{
int t = v[2];
v[2] = v[3];
v[3] = t;
}
bfs();
}
return 0;
}
最先出现的目标是最少的次数
隐式图
优先队列priority queue
hdoj 1242 rescue
优先队列方法
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <queue>
#define MAXN 10000
using namespace std;
char map[1100][1100];
int vis[1100][1100];
int n, m;
int mi;
int sx, sy, ex, ey;
int dx[5] = {1, -1, 0, 0};
int dy[5] = {0, 0, 1, -1};
struct st
{
int x;
int y;
int time;
bool friend operator<(st a, st b)
{
return a.time > b.time;
}
};
bool judge(st a)
{
if (a.x < 0 || a.x >= n || a.y < 0 || a.y >= m || map[a.x][a.y] == '#' || vis[a.x][a.y])
return false;
return true;
}
int bfs(int x, int y)
{
priority_queue<st> q;
while (!q.empty())
q.pop();
st a;
a.x = x;
a.y = y;
a.time = 0;
vis[x][y] = 1;
q.push(a);
while (!q.empty())
{
st b = q.top();
q.pop();
if (map[b.x][b.y] == 'a')
return b.time;
for (int i = 0; i < 4; i++)
{
st end;
end.x = b.x + dx[i];
end.y = b.y + dy[i];
end.time = b.time;
if (judge(end))
{
if (map[end.x][end.y] == 'x')
end.time++;
end.time++;
q.push(end);
vis[end.x][end.y] = 1;
}
}
}
return 0;
}
int main()
{
while (~scanf("%d%d", &n, &m))
{
memset(map, 0, sizeof(map));
for (int i = 0; i < n; i++)
{
scanf("%s", map[i]);
}
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
{
if (map[i][j] == 'r')
{
memset(vis, 0, sizeof(vis));
int ans = bfs(i, j);
if (ans < mi)
mi = ans;
}
}
memset(vis, 0, sizeof(vis));
if (mi == 0)
printf("Poor ANGEL has to stay in the prison all his life.\n");
else
printf("%d\n", mi);
}
return 0;
}
老刘说了一句话,你们在掉了几百块钱很伤心,但是很多人不来我的课。其实我讲课几百块钱一小时。你想交钱我还不一定教
定义好一类规则就行了,长得最帅的出去,全部都出去了
优先队列其实是一个大顶堆,什么是堆呢?堆就是一个拟满二叉树,最后一层的上面全是满的。最后一层全部靠左
前缀编码里面没有前缀
我去找老师---学生找到我
在一个命名空间可以少打两次
greater表示小顶堆
硬着头皮写,问同学
不理解不要写上去,为每一句话负责
收获信息港
剪枝优化,动态规划和搜索都是最优的子问题
有什么问题可以加qq:1281372141进行交流