第四周 搜索

dfs与bfs的初探

题目描述

给定一个N×M 方格的迷宫,迷宫里有 T 处障碍,障碍处不可通过。

在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。

输入格式

第一行为三个正整数 N,M,T分别表示迷宫的长宽和障碍总数。

第二行为四个正整数 SX,SY,FX,FY,SX,SY 代表起点坐标FX,FY 代表终点坐标。

接下来 TT 行,每行两个正整数,表示障碍点的坐标。

输出格式

输出从起点坐标到终点坐标的方案总数。

输入输出样

输入 #1

2 2 1
1 1 2 2
1 2

输出 #1 

这题是得出方案总数,就是得一次次搜索, 然后一次次加在一起

#include <bits/stdc++.h>
using namespace std;
int sx,sy,fx,fy;
int sum;
int mp[6][6];//建立一个二维数组来储存地图的样子 
int jl[6][6];//用来记录这个点是否走过防止反复横跳 
int xb[4]={0,0,-1,1};//上下左右的运动数组 
int yb[4]={-1,+1,0,0};
void zl(int x,int y){//递归函数 
	if(x==fx&&y==fy){
		sum++;//如果点刚好是终点,那就sum++在continue继续递归 
		return;
	}
	else{//如果不是终点,那就让这个点移动起来 
		for(int i=0;i<4;i++){//上下左右四个方向移动 
			if(jl[x+xb[i]][y+yb[i]]==0&&mp[x+xb[i]][y+yb[i]]==1){//如果下一个点没有走过,并且不是障碍物,就走到下一个点 
				jl[x][y]=1;//把这个点纪录一下 
				zl(x+xb[i],y+yb[i]);//走到下一个点 
				jl[x][y]=0;//把上一个记录完的点取消掉 
			}
		}
	}
}/*问题1递归函数结束的条件在哪里体现 
问题2  什么时候开始递归 
*/ 
int main()
{
	int n,m,t;
	cin>>n>>m>>t;
	cin>>sx>>sy>>fx>>fy;
	int x,y;
	jl[sx][sy]=1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			mp[i][j]=1;
		}
	}
	for(int i=1;i<=t;i++){
		cin>>x>>y;
		mp[x][y]=0;
	}
	zl(sx,sy);
	cout<<sum;
	return 0;
}

下面一题bfs

题目描述

有一个n×m 的棋盘,在某个点(x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。

输入格式

输入只有一行四个整数,分别为 n, m, x, y。

输出格式

一个 n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 −1)。

输入输出样例

输入 #1

3 3 1 1

输出 #1

0    3    2    
3    -1   1    
2    1    4    

这题要求的就是从初始的位置开始,对于数组中每一个位置都去搜索,广搜,每个位置都来一次

如果马能到这个位置,就显示走到这个位置所需要的次数,如果不能到达这个位置就输出-1

所以我们一开始就可以把记录用的数组赋值为-1,方便输出

记住,在棋盘上,马走的是日字 ,而且一匹马,在一个位置有八种走法,所以对于基础的迷宫走法来说,我们要在上面加点科技与狠活

广搜一般是通过queue来实现的

#include <bits/stdc++.h>
using namespace std;
int qp[405][405];
int jl[405][405];
int xd[8]={2, 2,-1,-1, 1, 1,-2,-2};//马有八种运动方式 
int yd[8]={1,-1, 2,-2, 2,-2, 1,-1};  
queue<pair<int,int> > q;//pair那里的>要和queue那里的>中间加上一个空格防止被c++默认为>> 
int main(){
	int n,m,kx,ky;//kxky记录开始位置 
	cin>>n>>m>>kx>>ky;
	memset(qp,-1,sizeof(qp));//给二维数组qp全部赋值为-1,因为马走不到返回值为-1
	qp[kx][ky]=0;//一开始的位置不需要移动就能到达,特殊位置特殊出来赋值为0;
	jl[kx][ky]=1;//再把开始的地方记录为已经走过了
	q.push(make_pair(kx,ky));
	while(!q.empty()){//开始bfs 
		int nx=q.front().first;//用front来获取队列中第一个成员 
		int ny=q.front().second;
		q.pop();
		for(int i=0;i<8;i++){
			int next_x=nx+xd[i];
			int next_y=ny+yd[i];
			if(next_x>=1&&next_x<=n&&next_y>=1&&next_y<=m&&jl[next_x][next_y]==0){//x与y不越界,并且这个点没有走过 
				q.push(make_pair(next_x,next_y));
				jl[next_x][next_y]=1;
				qp[next_x][next_y]=qp[nx][ny]+1;
			}
		}
	}
	for(int i=1; i<=n; i++){
		for(int j=1; j<=m; j++){
			printf("%-5d",qp[i][j]);//-表示左对齐,默认为右对齐 
		}
		cout<<endl;
	}
	return 0;
}

 匆匆忙忙,下周一定丰满

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值