YbtOJ 广度搜索课堂过关 例3 立体推箱子【bfs】

102 篇文章 2 订阅
21 篇文章 0 订阅

在这里插入图片描述


思路

首先这个是广搜。
可以预处理出刚开始的箱子状态和终点。
那么 1 × 2 1\times 2 1×2 的情况怎么记录呢?
我们可以记录第一个格子,然后直接把第二个格子判断状态即可。
然后对于箱子的移动很麻烦,我们要用 d x , d y , d t dx,dy,dt dx,dy,dt 分别表示每种情况下的移动方式。
最后直接搜就好了。

C o d e Code Code

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int dx[4][5]={{},{0,0,1,0,-2},{0,0,1,0,-1},{0,0,2,0,-1}};
const int dy[4][5]={{},{0,1,0,-2,0},{0,2,0,-1,0},{0,1,0,-1,0}};
const int dt[4][5]={{},{0,2,3,2,3},{0,1,2,1,2},{0,3,1,3,1}};
int v[510][510][4];
char a[510][510],c;
int n,m,tx,ty;
struct node
{
	int x,y,t,c;
}f[10001000];
bool check(int x,int y,int t)
{
	if(x<1||x>n||y<1||y>m||v[x][y][t]==1)
	  return 0;
	if(t==1)
	 {
	 	if(a[x][y]=='E'||a[x][y]=='#')
	 	  return 0;
	 }
	if(t==3)
	 {
	 	if(a[x][y]=='#'||x+1>n||a[x+1][y]=='#')
	 	  return 0;
	 }
	if(t==2)
	 {
	 	if(a[x][y]=='#'||y+1>m||a[x][y+1]=='#')
	 	  return 0;
	 }
	return 1;
}
void bfs()
{
	int hd=0,tl=1;
	while(hd<tl)
	 {
	 	hd++;
	 	for(int i=1; i<=4; i++)
	 	 {
	 	 	int xx=f[hd].x+dx[f[hd].t][i];
	 	 	int yy=f[hd].y+dy[f[hd].t][i];
	 	 	int tt=dt[f[hd].t][i];
	 	 	if(check(xx,yy,tt))
	 	 	 {
	 	 	 	tl++;
	 	 	 	f[tl]=(node){xx,yy,tt,f[hd].c+1};
	 	 	 	if(xx==tx&&yy==ty&&tt==1)
	 	 	 	 {
	 	 	 	 	cout<<f[tl].c<<endl;
	 	 	 	 	return;
				 }
				v[xx][yy][tt]=1;
			 }
		 }
	 }
	cout<<"Impossible"<<endl;
}
void ycl()
{
	int w=0;
	for(int i=1; i<=n; i++)
	 for(int j=1; j<=m; j++)
	  {
	  	if(a[i][j]=='X'&&w==0)
	  	 {
	  	 	w=1;
	  	 	if(a[i][j+1]=='X')
	  	 	  f[1].x=i,f[1].y=j,f[1].t=2;
	  	 	else if(a[i+1][j]=='X')
	  	 	  f[1].x=i,f[1].y=j,f[1].t=3;
	  	 	else
	  	 	  f[1].x=i,f[1].y=j,f[1].t=1;
	  	 	v[i][j][f[1].t]=1;
		 }
		if(a[i][j]=='O')
		  tx=i,ty=j;
	  }
}
int main()
{
	while(cin>>n>>m)
	 {
	   memset(v,0,sizeof(v));
	   if(n==0&&m==0)
	     break;
	   for(int i=1; i<=n; i++)
	    for(int j=1; j<=m; j++)
	     {
	  	    a[i][j]=getchar();
	  	    while(a[i][j]!='#'&&a[i][j]!='X'&&a[i][j]!='.'&&a[i][j]!='O'&&a[i][j]!='E')
	  	      a[i][j]=getchar();
	     }
	   ycl();
	   bfs();
	 }
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是使用BFS算法实现推箱子游戏的C++代码示: ```cpp #include <iostream> #include <queue> #include <vector> using namespace std; struct State { int bx, by; // 箱子的位置 int px, py; // 人的位置 int steps; // 步数 }; int main() { int n, m; // 地图的行数和列数 cin >> n >> m; vector<vector<char>> map(n, vector<char>(m)); // 地图 vector<vector<vector<vector<bool>>>> visited(n, vector<vector<vector<bool>>>(m, vector<vector<bool>>(n, vector<bool>(m, false)))); // 记录访问状态 int bx, by, px, py, tx, ty; // 箱子、人和目标位置的坐标 for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> map[i][j]; if (map[i][j] == 'B') { bx = i; by = j; } else if (map[i][j] == 'S') { px = i; py = j; } else if (map[i][j] == 'T') { tx = i; ty = j; } } } queue<State> q; q.push({bx, by, px, py, 0}); visited[bx][by][px][py] = true; int dx[] = {-1, 1, 0, 0}; // 上下左右四个方向的偏移量 int dy[] = {0, 0, -1, 1}; while (!q.empty()) { State curr = q.front(); q.pop(); if (curr.bx == tx && curr.by == ty) { cout << curr.steps << endl; // 输出最少步数 return 0; } for (int i = 0; i < 4; i++) { int nx = curr.bx + dx[i]; int ny = curr.by + dy[i]; int px = curr.bx - dx[i]; int py = curr.by - dy[i]; if (nx >= 0 && nx < n && ny >= 0 && ny < m && px >= 0 && px < n && py >= 0 && py < m && map[nx][ny] != '#' && map[px][py] != '#' && !visited[nx][ny][curr.bx][curr.by]) { q.push({nx, ny, curr.bx, curr.by, curr.steps + 1}); visited[nx][ny][curr.bx][curr.by] = true; } } } cout << -1 << endl; // 无法到达目标位置 return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值