Maze(dfs和bfs)

题意

Edward is trapped in a grid maze! A grid maze is an n×n square maze where each cell is either empty, or is a wall. Edward can go from one cell to another only if both cells are empty and have a common side.

The starting position of Edward is located at the si-th row and the sj-th column of the maze. In order to escape, Edward has to first get the key located at the ki-th row and the kj-th column of the maze, and then move to the exit located at the ei-th row and the ej-th column of the maze. Of course, Edward can move into (ei, ej) even if he hasn’t get the key yet, but he can’t escape from the maze through the exit at that time.

It takes Edward 1 second to move from one cell to another. Can you help Edward calculate the minimum time he needs to escape from the maze?

输入

There are multiple test cases. The first line of input contains an integer T (1 ≤ T ≤ 10), indicating the number of test cases. For each test case:

The first line contains seven integers n, si, sj, ki, kj, ei, ej (2 ≤ n ≤ 100, 1 ≤ si, sj, ki, kj, ei, ej ≤ n), indicating the size of the maze, the starting position, the position of the key and the position of the exit.

For the following n lines, the i-th line contains n integers ai, 1, ai, 2, …, ai, n (0 ≤ ai, j ≤ 1). ai, j indicates the cell at the i-th row and the j-th column of the maze. If ai, j equals 0, then the cell is empty, otherwise the cell is blocked.

It’s guaranteed that (si, sj) ≠ (ki, kj), (si, sj) ≠ (ei, ej) and (ki, kj) ≠ (ei, ej). None of the starting position, the position of the key and the position of the exit is blocked. And it’s guaranteed that Edward can always escape from the maze.

输出

For each test case output one line containing one integer, indicating the shortest time Edward needs to escape.

样例输入

2
3 1 1 3 1 3 3
0 0 0
0 1 0
0 1 0
2 1 1 1 2 2 2
0 0
1 0

样例输出

8
2

The optimal path for Edward in the first test case is (1, 1) -> (2, 1) -> (3, 1) -> (2, 1) -> (1, 1) -> (1, 2) -> (1, 3) -> (2, 3) -> (3, 3), so the answer is 8.

解题思路

题目的意思就是你刚开始在(si,sj),你要先去(ki,kj),然后再从(ki,kj)到(ei,ej),问最短的时间是多少。
我用dfs写结果超时了,就用bfs了,但是我太讨厌用bfs了,还要用队列和结构体,太麻烦了。
就是你要一个个搜,找到最小的就行啦

程序代码:(dfs)-TLE

#include<bits/stdc++.h>
using namespace std;
const int dirx[4]={-1,1,0,0}//确定四个方向 
		 ,diry[4]={0,0,1,-1};
const int N=100+10;
const int INF=0x3f3f3f3f;
int n,ans=INF,sum=0;
int s[N][N],a[N][N];//s记录迷宫图,a记录是否被访问过 
void  dfs(int x,int y,int ax,int ay)
{
    if(x==ax&&y==ay)
    {
        ans=min(ans,sum);
        return ;
    }
    for(int i=0;i<4;i++)//依次访问该点周围四个方向
    {
        int nx=x+dirx[i];
        int ny=y+diry[i];
        if(nx>=1&&nx<=n&&ny>=1&&ny<=n&&s[nx][ny]==0&&a[nx][ny]==0)//前四个为判断是否在迷宫中  最后一个是判断该点是否被访问过
        {
            a[nx][ny]=1;
            sum++;
            dfs(nx,ny,ax,ay);//是没访问过的点并且是可行点,就继续搜索
            sum--;
            a[nx][ny]=0;//回溯,重新置为0,方便下次访问
        }
    }
    return ;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		memset(s,0,sizeof(s));
		memset(a,0,sizeof(a));
		ans=INF;
		sum=0;
		int sx,sy,kx,ky,ex,ey;
		scanf("%d %d %d %d %d %d %d",&n,&sx,&sy,&kx,&ky,&ex,&ey);
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				scanf("%d",&s[i][j]);
		a[sx][sy]=1;
		dfs(sx,sy,kx,ky);
		int temp=ans;
		memset(a,0,sizeof(a));
		ans=INF;
		sum=0;
		a[kx][ky]=1;
		dfs(kx,ky,ex,ey);
		int temp1=ans;
		printf("%d\n",temp+temp1);
	}
	return 0;
} 

程序代码:(bfs)-AC

#include<bits/stdc++.h>
using namespace std;
struct node{
	int x,y;	//当前结点在图上的坐标 
	int step;	//表示到达当前结点所需的步数 
};
const int dir[4][4]={{0,1},{1,0},{0,-1},{-1,0}};//确定四个方向
const int N=100+10;
int s[N][N],a[N][N];//s记录迷宫图,a记录是否被访问过 
int n;
int bfs(int x,int y,int ax,int ay){
	node start;
	start.x = x,start.y = y;
	start.step = 0;
	memset(a,0,sizeof(a));
	queue<node> q;
	q.push(start); //将起点进行入队操作。 
	a[start.x][start.y] = 1;
	while(!q.empty()){
		node now = q.front();
		q.pop(); //将当前节点进行出队。 
		for(int i=0;i<4;i++){ //每次循环分别对当前节点对四周节点进行访问 
			int nx = now.x+dir[i][0];
			int ny = now.y+dir[i][1];
			node next;//即将入队的节点
			if(a[nx][ny]==0&&s[nx][ny]==0&&nx>=1&&nx<=n&&ny>=1&&ny<=n){
				a[nx][ny] = 1;//将已访问节点进行标注 
				next.x = nx;
				next.y = ny;
				next.step = now.step+1; 
				q.push(next); //将下一个节点进行入队操作 
			}
			if(nx==ax&&ny==ay){ //当已经到达终点时返回 
				return next.step; //返回从初始点到终点所需要的步数 
			} 
		}		
	}
	return 0; //查找失败没有找到对应的路线 
} 
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
//		memset(s,0,sizeof(s));
//		memset(a,0,sizeof(a));
		int sx,sy,kx,ky,ex,ey;
		scanf("%d %d %d %d %d %d %d",&n,&sx,&sy,&kx,&ky,&ex,&ey);
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				scanf("%d",&s[i][j]);
		int ans=bfs(sx,sy,kx,ky);
		int ans1=bfs(kx,ky,ex,ey);
		printf("%d\n",ans+ans1);
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是对DFSBFS和UCS的介绍: DFS(深度优先搜索):总是扩展最深层的节点,使用的是LIFO队列,即使用的是stack栈。DFS在生成节点时做的goal test,因此在搜索树中,DFS总是沿着最深的路径搜索,直到找到目标状态或者无法继续搜索为止。DFS的优点是空间复杂度低,但是可能会陷入局部最优解。 BFS(广度优先搜索):总是扩展最浅层的节点,使用的是FIFO队列,即使用的是queue队列。BFS在扩展节点时做的goal test,因此在搜索树中,BFS总是沿着最浅的路径搜索,直到找到目标状态或者无法继续搜索为止。BFS的优点是可以找到最优解,但是空间复杂度较高。 UCS(最佳优先搜索):总是扩展当前代价最小的节点,使用的是priority queue优先队列。UCS在扩展节点时做的goal test,因此在搜索树中,UCS总是沿着代价最小的路径搜索,直到找到目标状态或者无法继续搜索为止。UCS的优点是可以找到最优解,且可以在frontier集中记录所有合适的解,但是空间复杂度较高。 以下是对DFSBFS和UCS的演示: 假设我们要在一个迷宫中找到从起点到终点的最短路径,其中1表示墙,0表示可以通过的路。迷宫如下所示: ``` 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 0 0 0 0 1 1 0 1 0 1 0 1 1 0 1 1 0 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 1 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 1 0 0 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 ``` 我们可以使用DFSBFS和UCS来寻找最短路径。其中DFS使用stack栈,BFS使用queue队列,UCS使用priority queue优先队列。具体实现可以参考以下代码: ```python # DFS def dfs(maze, start, end): stack = [(start, [start])] visited = set() while stack: node, path = stack.pop() if node == end: return path if node not in visited: visited.add(node) for neighbor in get_neighbors(maze, node): stack.append((neighbor, path + [neighbor])) return None # BFS def bfs(maze, start, end): queue = [(start, [start])] visited = set() while queue: node, path = queue.pop(0) if node == end: return path if node not in visited: visited.add(node) for neighbor in get_neighbors(maze, node): queue.append((neighbor, path + [neighbor])) return None # UCS def ucs(maze, start, end): queue = [(0, start, [start])] visited = set() while queue: cost, node, path = heapq.heappop(queue) if node == end: return path if node not in visited: visited.add(node) for neighbor in get_neighbors(maze, node): new_cost = cost + 1 heapq.heappush(queue, (new_cost, neighbor, path + [neighbor])) return None # 获取邻居节点 def get_neighbors(maze, node): neighbors = [] row, col = node if row > 0 and maze[row-1][col] == 0: neighbors.append((row-1, col)) if row < len(maze)-1 and maze[row+1][col] == 0: neighbors.append((row+1, col)) if col > 0 and maze[row][col-1] == 0: neighbors.append((row, col-1)) if col < len(maze[0])-1 and maze[row][col+1] == 0: neighbors.append((row, col+1)) return neighbors ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值