两种相爱相杀的搜索算法(BFS & DFS)

BFS:

当知道初始和目标状态的,用双向BFS:
无权图最好用BFS
不用重复如队

实现框架:

抄来的(来源:https://www.luogu.org/blog/stephen2333/solution-p1135)
ps: 我一开始也写过,不过真心觉得他写的好

1、对于初始状态入队,设置初始状态为已访问
2、如果队列不为空时,出队队头元素,否则跳到第5步
3、检查出队的元素是否为最终解,如果是则跳到第5步。
4、对于出队的元素,检查所有相邻状态,如果有效并且未访问,则将
所有有效的相邻状态进行入队,并且设置这些状态为已访问,然后
跳到第2步重复执行
5、检查最后出队的元素是否为最终解,如果是输出结果,否则说明无解

通常用队列(先进先出,FIFO)实现

初始化队列q;
q = {起点u};标记s为已访问;
while(q为非空){
去q队首元素 now;now出队;
If(now == 目标状态) {….}
所有与now 相连 并 且未被访问的点进入队列(没被标记);
并标记now已访问;
}

矩形宽搜:

题目描述
一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。(1<=m,n<=100)?
输入输出格式
输入格式:

输入:整数m,n(m行,n列)
矩阵
输出格式:

输出:细胞的个数
/*
4 10
0 2 3 4 5 0 0 0 6 7
1 0 3 4 5 6 0 5 0 0
2 0 4 5 6 0 0 6 7 1
0 0 0 0 0 0 0 0 8 9
*/

#include<cstdio>
#define maxn 100

int m,n,cnt = 0;
char s[maxn];
int a[maxn][maxn],vis[maxn][maxn];

int q[maxn];
int movex[5] = {0,1,-1,0,0};
int movey[5] = {0,0,0,1,-1};

void bfs(int x, int y) {
	int l = 0, r = 0;
	q[r++] = x;
	q[r++] = y;//按顺序加入  取出时就是按的这个顺序取出
	while(l < r) {//当 l = r时 队列为空  就找完第53行传入的点附近的数(可以和它构成cells的) 
		int nowx = q[l++];
		int nowy = q[l++];//取出当前点的位置
		for(int i = 1; i <= 4; i++) {//判断四个方向(上下左右)的数  
			int ix = nowx + movex[i];//当前(四个之一)方向上的坐标
			int iy = nowy + movey[i];
			if(ix < 1 || iy < 1 || ix > n || iy > m) continue;//一定要写!!!矩阵的bfs的边界 
			//if(ix == 0 || iy == 0 || ix || ix > n || iy > m)  continue;//最好写上面的 
			if(a[ix][iy]) {
				if(!vis[ix][iy]) {//再次判断它用不用被选 选过之后就没必要选了 
					vis[ix][iy] = 1;
					q[r++] = ix;
					q[r++] = iy;//入队 
				} 
			}
		}
	}
}

int main() {
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n; i++) {
		scanf("%s",s);//先输入一行较长的字符数组,因为原题的没有空格 
		for(int j = 1; j <= m; j++) {
			a[i][j] = s[j - 1] - '0';//s[j - 1]是s的第一个元素 
		}
	}
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= m; j++) {
			if(!vis[i][j]) {//找出没有走过的点
				vis[i][j] = 1;//做标记
				if(a[i][j]) { //这才是找到可以宽搜的 点
					bfs(i,j);
					cnt++;
				}
			}
		}
	}
	printf("%d",cnt);
}

DFS;

通常搜出组合方式,求最优解的时候,我们考虑用DFS

数据结构:系统栈;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值