算法题——广度优先搜索
BFS访问二叉树
package cn.ganlixin.bfs;
import java.util.LinkedList;
import java.util.Queue;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
}
}
public class BFS {
/**
* 广度优先搜索,需要借助一个队列
*
* @param root
*/
public static void bfs(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root); // 根节点入队
// 可以使用一个set标记已经走过的节点
// Set<TreeNode> visited = new HashSet<>();
while (!queue.isEmpty()) {
// 元素出队
TreeNode node = queue.poll();
//visited.add(node); // 标记为已经处理过
// 进行操作
// process(node);
System.out.print(node.val + " ");
// 将出队元素的左右子节点依次入队
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
public static void main(String[] args) {
/*
1
/ \
2 3
\ / \
4 5 6
*/
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.right = new TreeNode(4);
root.right.left = new TreeNode(5);
root.right.right = new TreeNode(6);
bfs(root); // 1 2 3 4 5 5
}
}
例题1:Catch that cow
在一个数轴上,有一个农民位于n的位置处,有一头牛位于k的位置处,农民有三种走路方式:
①若农民位于x,农民可以移动一步到x-1或x+1
②若农民位于x,农民可以跳跃到2*x处
问:农民需要最少多少步抓住那头牛?
Sample Input
5 24
100 100
Sample Output
3
0
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
struct step{
int addr; // 当前位置
int cnt; //走到当前位置,走的步数
};
int start; //农夫的起点
int target; //奶牛的位置
bool visit[10000]; //标记某个位置是否走过。
int a[10000]; // 记录是从哪一个位置走到这个位置的,即父亲位置
//打印路径
void printPath(int cnt) {
int parent;
int path [cnt];
path[cnt] = target;
for (int i = 0; i < cnt; i++) {
parent = a[target];
target = parent;
path[cnt - i - 1] = parent;
}
for (int i = 0; i <= cnt; i++) {
cout << path[i] << " ";
}
cout << endl;
}
int bfs(step s) {
memset(visit, false, 10000);
memset(a, 0, 10000);
queue<step> Q; //一个队列
Q.push(s); //首先,原始位置入队
while (!Q.empty()) { // 队列不为空
step cur = Q.front(); //获取队头元素
for (int i = 0; i < 3; i++) {
step tmp;
if (i == 0 && cur.addr-1 > 0 && !visit[cur.addr - 1]) {
tmp.addr = cur.addr - 1;
} else if (i == 1 && cur.addr+1 <= 10000 && !visit[cur.addr + 1]) {
tmp.addr = cur.addr + 1;
} else if (i == 2 && cur.addr*2 <= 10000 && !visit[cur.addr * 2]){
tmp.addr = cur.addr * 2;
}
tmp.cnt = cur.cnt + 1; // 从当前位置到左边一个位置,步数要加1
a[tmp.addr] = cur.addr; // 记录器父位置
visit[tmp.addr] = true; // 将新位置标记为已走过
if (cur.addr == target) { //如果当前位置是奶牛的位置
cout << cur.cnt << endl; // 直接输出到当前位置所走的步数
printPath(cur.cnt);
return 0;
}
Q.push(tmp); //新入队的值不是目标节点
}
Q.pop(); //队首出队,因为他的下一层已经全部入队了
}
cout << "不可达" << endl;
}
int main(){
cin >> start >> target;
if (start == target) {
cout << 0 << endl;
return 0;
}
step s; //农夫初始位置
s.addr = start;
s.cnt = 0; // 从初始位置到初始位置的步数为0.
visit[s.addr] = true; //将初始位置标记为走过
bfs(s);
return 0;
}
例题2:从src到dest需要几步
有一点处于(x1,y1)位置上,他可以向相临8个位置移动(移动方式见下图)。
划定范围:此点只可以在[0<=x<=300,0<=y<=300]范围内移动。
要求:给出起始位置(x1,y1)和目标位置(x2,y2),要求同学求出从起始位置移动到目标位置所需的最少次数。
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
struct addr{
int x;
int y;
int cnt;
};
addr s; //初始位置
addr t; //目标位置
bool visit[300][300];
int bfs(addr s) {
s.cnt = 0;
memset(visit, false, sizeof(visit));
visit[s.x][s.y] = true; //将初始位置标记为已走过
queue<addr> Q; //一个队列
Q.push(s); //首先,原始位置入队
while (!Q.empty()) { // 队列不为空
addr cur = Q.front(); //获取队头元素
if (cur.x == t.x && cur.y == t.y) { //如果当前位置是目标位置
cout << cur.cnt << endl; // 直接输出到大当前位置所走的步数
return 0;
}
if ( (cur.x-1)>=0 && (cur.y-2)>=0 && !visit[cur.x-1][cur.y-2]) {
addr tmp;
tmp.x = cur.x-1;
tmp.y = cur.y-2;
tmp.cnt = cur.cnt + 1;
visit[cur.x-1][cur.y-2] = true;
Q.push(tmp);
}
if ( (cur.x-2)>=0 && (cur.y-1)>=0 && !visit[cur.x-2][cur.y-1]) {
addr tmp;
tmp.x = cur.x-2;
tmp.y = cur.y-1;
tmp.cnt = cur.cnt + 1;
visit[cur.x-2][cur.y-1] = true;
Q.push(tmp);
}
if ( (cur.x-2)>=0 && (cur.y+1)<=300 && !visit[cur.x-2][cur.y+1]) {
addr tmp;
tmp.x = cur.x-2;
tmp.y = cur.y+1;
tmp.cnt = cur.cnt + 1;
visit[cur.x-2][cur.y+1] = true;
Q.push(tmp);
}
if ( (cur.x-1)>=0 && (cur.y+2)<=300 && !visit[cur.x-1][cur.y+2]) {
addr tmp;
tmp.x = cur.x-1;
tmp.y = cur.y+2;
tmp.cnt = cur.cnt + 1;
visit[cur.x-1][cur.y+2] = true;
Q.push(tmp);
}
if ( (cur.x+1)<=300 && (cur.y-2)>=0 && !visit[cur.x+1][cur.y-2]) {
addr tmp;
tmp.x = cur.x+1;
tmp.y = cur.y-2;
tmp.cnt = cur.cnt + 1;
visit[cur.x+1][cur.y-2] = true;
Q.push(tmp);
}
if ( (cur.x+2)<=300 && (cur.y-1)>=0 && !visit[cur.x+2][cur.y-1]) {
addr tmp;
tmp.x = cur.x+2;
tmp.y = cur.y-1;
tmp.cnt = cur.cnt + 1;
visit[cur.x+2][cur.y-1] = true;
Q.push(tmp);
}
if ( (cur.x+1)<=300 && (cur.y+2)<=300 && !visit[cur.x+1][cur.y+2]) {
addr tmp;
tmp.x = cur.x+1;
tmp.y = cur.y+2;
tmp.cnt = cur.cnt + 1;
visit[cur.x+1][cur.y+2] = true;
Q.push(tmp);
}
if ( (cur.x+2)<=300 && (cur.y+1)<=300 && !visit[cur.x+2][cur.y+1]) {
addr tmp;
tmp.x = cur.x+2;
tmp.y = cur.y+1;
tmp.cnt = cur.cnt + 1;
visit[cur.x+2][cur.y+1] = true;
Q.push(tmp);
}
Q.pop(); //队首出队,因为他的下一层已经全部入队了
}
return 0;
}
int main(){
while (cin >> s.x >> s.y >> t.x >>t.y) {
bfs(s);
}
return 0;
}
如需转载,请注明文章出处,谢谢!!!

浙公网安备 33010602011771号