目录
广度优先搜索 BFS
一层一层的搜
运用数据结构 队列 queue 先进先出
queue<T> 队列名front() 返回队首元素值
push() 入队尾
pop() 让队首元素出队
empty() 判断队列是否为空
没有clear
可以循环出队 直到队空 等效 clear while( !q.empty() ) q.pop()
#include <iostream>
using namespace std;
#include<queue>
#include<string>
报数游戏 (约瑟夫环)
报到数n的人出队,输出最后剩下的人的序号
样例输入:
7 5输出:
6
void test_01() {
int n,m; //n为人数 , m为报到需要出队的数
cin >> n>> m;
queue<int > q;
for(int i = 1; i <= n; i++) { //编号从1开始
q.push(i);
}
int cur = 1; //当前正在报的数
while(q.size() > 1) { //剩最后一人
int x = q.front(); //*** 存队头,队头不断变换 , 先出队看是不是报m 出队,不是把x == q.front()放队尾,
q.pop();
if(cur == m) { //重新一轮报
cur = 1;
} else {
q.push(x); //放入不出队的
cur++;
}
}
cout<< q.front();
return;
}
迷宫的bfs 走一步能走到哪,走两步能到哪...
能搜最短路径样例输入:
5 6
....S*
.**...
.*..*.
*..**.
.T....输出:
7
char maze_02[100][100];
int n_02,m_02;
bool vis_02[100][100];
int dir_02[4][2] = { {-1,0},{0,-1},{1,0},{0,1} } ;
bool in_02(int x,int y) { //不越界
return 0 <= x && x< n_02 && 0 <= y && y < m_02;
}
struct node_02 { //用队列存放坐标,创一个结构体
int x,y,d;
node_02(int xx,int yy,int dd) {
this->x = xx;
y = yy;
d = dd;
}
};
int bfs_02(int sx, int sy) { //strat起始坐标 (x,y)
queue<node_02> q; //结构体类型!!!
q.push(node_02(sx,sy,0));//存放起始点
vis_02[sx][sy] = true; //起点可以走
while(!q.empty()) {
node_02 now = q.front(); //当前坐标 进行下一步搜索 ,先出队 存结构体变量.
q.pop();
for(int i = 0; i < 4; i++) { //遍历搜索
int tx = now.x + dir_02[i][0];
int ty = now.y + dir_02[i][1];
if(in_02(tx,ty) && maze_02[tx][ty] != '*' && !vis_02[tx][ty] ) { //允许走的条件 不越界、无障碍 、 未标记走过
if(maze_02[tx][ty] == 'T') { //到终点
return now.d + 1; //返回步数
} else {
vis_02[tx][ty] = true; //判断可以走,此步状态改为true ,即可走到此步
q.push(node_02(tx,ty,now.d + 1)); //搜索
// cout << now.d <<endl;//?
}
}
}
}
return -1; //没有找到
}
void test_02() {
cin >> n_02 >> m_02;
for(int i = 0; i < n_02; i++) {
cin >> maze_02[i] ;
}
/*测试
for(int i = 0; i < n_02; i++) {
cout << maze_02[i] <<endl;
}*/
int x,y;
for(int i = 0; i < n_02; i++) {
for(int j = 0; j < m_02; j++) {
if(maze_02[i][j] == 'S') { //找起点 ( == 等于 !!! 第二次调试半天 输出x,y值不对发现)
x = i;
y = j;
}
}
}
cout<< bfs_02(x,y) <<endl;
return;
}
坐标移动
长度为n的坐标轴,从A点移动到B点 ,遵循以下规则
1.向前一步 ,坐标增加1
2.向后一步,坐标减少1
3.跳跃一步,坐标乘2第一行输入 n,A,B //分别代表坐标轴长度,起点坐标,终点坐标 [0,5000]
输出最小步数样例输入:
10 2 7输出:
3
queue<pair<int,int > > q; //第二次q可能不空就退出,要手动清,才再次进行遍历
bool vis[5005];
void test_03() {
int n,A,B,now,step; //now现在位置 step步数
scanf("%d%d%d",&n,&A,&B);
q.push(make_pair(A,0)); //now + 1,step + 1
vis[A] = true;
while(!q.empty()) {
now = q.front().first; //当前
step = q.front().second; //下一步
q.pop();
if(now == B){ //结束
cout<< step << endl;
break;
}
if(now + 1 <= n && !vis[now + 1]){ //加一
q.push(make_pair(now + 1,step + 1));
vis[now - 1] = true;
}
if(now - 1 >= 0 && !vis[now - 1]){ //减一
q.push(make_pair(now - 1,step + 1));
vis[now - 1] = true;
}
if(now * 2 <= n && !vis[now * 2]){ //乘二
q.push(make_pair(now * 2,step + 1));
vis[now * 2] = true;
//测试cout<<2;
}
}
}
密码锁
四位密码 ,每位均为1-9中的一个
当9 加 1 时将变为1,当1减1时变回9 (环形)第一行输入4位数,表示密码锁的初始状态
第二行输入4位数 ,表示开锁的密码输出一个整数,表示最小步骤 (用BFS)
样例输入:
1234
2144
输出:
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
/*
using namespace std;
struct node{
int num[4],step;
}first,second;
int vis[11][11][11][11s];
void bfs(){
int i;
node a,next;
queue<node> q;
a =first;
a.step;
}
void test_04(){
int i,j,t;
char s1[10],s2[10];
scanf("%s%s",s1,s2); //字符串读入
for(i = 0;i < 4;i++){ //转成数字
first.num[i] = s1[i] - '0';
last.num[i] = s2[i] - '0';
}
bfs();
return;
}
过于长之后补充 21 ...
草地 、跳棋 、 魔方还原 、 吃糖 、回家最短路线 、
void test_04(){
return;
}
int main() {
test_03();
return 0;
}