week 4 搜索(DFS与BFS)

T1:# 迷宫

## 题目描述

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

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

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

## 输入格式

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

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

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

## 输出格式

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

## 样例 #1

### 样例输入 #1

```
2 2 1
1 1 2 2
1 2
```

### 样例输出 #1

```
1
```

## 提示

对于 $100\%$ 的数据,$1 \le N,M \le 5$,$1 \le T \le 10$,$1 \le SX,FX \le n$,$1 \le SY,FY \le m$。

DFS(depth first search):深度优先搜索

解决枚举量过于大,

模板:

void dfs(一般是点x,或者层数)

{

        if(判断搜索完成)记录答案return;

        for枚举这个点走的方式{

                if判断这个方式是否合法{

                        标记这个点

                        dfs(下一个点)

                        取消这个点的标记(回溯)
            }

        }

}

图解:

  1. :存图

2:标记初始点

3.访问

 

代码:

#include<bits/stdc++.h>
using namespace std;
int N,M,T,sx,sy,fx,fy,ans;
int x,y,vis[10006][10006];
void dfs(int x,int y){
	if(x==fx&&y==fy){
		ans++;
		return;
	}//到达终点答案加加
	//向上走
	if(y<M&&vis[x][y+1]==0){
		vis[x][y+1]=1;
		dfs(x,y+1);
		vis[x][y+1]=0; 
	} 
	//向下走
	if(y>1&&vis[x][y-1]==0){
		vis[x][y-1]=1;
		dfs(x,y-1);
		vis[x][y-1]=0; 
	} 
	//向左走
	if(x>1&&vis[x-1][y]==0)
	{
		vis[x-1][y]=1;
		dfs(x-1,y);
		vis[x-1][y]=0;
	 } 
	 if(x<N&&vis[x+1][y]==0)
	 {
	 	vis[x+1][y]=1;
		dfs(x+1,y);
		vis[x+1][y]=0;
	 }
	 return;
}
int main()
{
	cin>>N>>M>>T>>sx>>sy>>fx>>fy;
	vis[sx][sy]=1;
	for(int i=1;i<=T;i++){
		int a,b;
		cin>>a>>b;
		vis[a][b]=1;
	}
	dfs(sx,sy);
	cout<<ans;
	return 0;
}

T2:马的遍历

## 题目描述

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

## 输入格式

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

## 输出格式

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

## 样例 #1

### 样例输入 #1
3 3 1 1

### 样例输出 #1
0    3    2    
3    -1   1    
2    1    4

## 提示

### 数据规模与约定

对于全部的测试点,保证 $1 \leq x \leq n \leq 400$,$1 \leq y \leq m \leq 400$。

BFS(Breadth first search):广度优先搜索

优先考虑搜索的深度,解决连通性,最短路问题,通过队列实现

模板:

q.push(初始点)//将初始点压入队列
while(!q.empty())//队列不为空时执行
{
    int n=q.front()//将队首的元素取出,并删除
    q.pop();
    for()枚举下一个状态的所有情况
    {
        int next=;
        if()//如果枚举的这个点合理
        {
            对它进行相应的操作,并把它压入队列尾
            q.push(next);
         }
    }
}

图解:

思路:

首先分析马走下一步可能的情况,一共八种,用数组分别储存这八组的变化的x,y;

然后:依据题意将未到达的点全部标记为-1

再:进行BFS,同时用一个dot二维数组记录答案

代码


#include<bits/stdc++.h>
using namespace std;
int N,M,sx,sy;
int nx[]={-2,-2,-1,-1,1,1,2,2};
int ny[]={1,-1,2,-2,2,-2,1,-1};
int dot[1006][1006];
queue <pair<int,int> > q;
int main()
{
	cin>>N>>M>>sx>>sy;
	memset(dot,-1,sizeof(dot));//标记未到达的地方全为-1(好处:不用判断哪个点没有走过 ) 
	dot[sx][sy]=0;//将出发点标记为零 
	q.push(make_pair(sx,sy));//将出发点压入队列 
	while(!q.empty()){
		int now_x=q.front().first,now_y=q.front().second;//弹出并删除队首的点 
		q.pop();
		for(int i=0;i<8;i++)//搜寻下一能到达的点 
		{
			int next_x=now_x+nx[i],next_y=now_y+ny[i];
			if(next_x<=N&&next_x>=1&&next_y<=M&&next_y>=1&&dot[next_x][next_y]==-1)
			{
				dot[next_x][next_y]=dot[now_x][now_y]+1;//这里不用担心少算了一步(开头将dot标记为-1),因为是从起点(0)开始算的 
				q.push(make_pair(next_x,next_y));//将能到达的点压入队列 
			}
		}
	}
	for(int i=1;i<=N;i++)
	{
		for(int j=1;j<=M;j++)
		{
			printf("%d    ",dot[i][j]);
		}
		cout<<endl;
	}
	return 0;
}

​

补充yhgg教的一个pair容器:

  1. 头文件:#include <utility>
  2. 定义:pair<数据类型,数据类型>
  3. 访问内部元素(仅有两个:p.first,p.second
  4. 赋值:可以赋值给同类型的pair对象s,s=make_pair(x,y)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值