POJ1475(Pushing Boxes)–bbffss

假设只有一个箱子。游戏在一个R行C列的由单位格子组成的区域中进行,每一步,

你可以移动到相邻的四个格子中的一个,前提是那个格子是空的;或者,如果你在箱子旁边,你也可以推动箱子前进一格,当然不能推到区域外面。

初始时你在其中某个格子内,你要把箱子推到指定格子。又由于箱子很重,所以你要用尽量少的推动次数。

Input

输入包含多组数据,每组数据第一行为两个正整数R和C,表示行数和列数。接下来R行,每行C个字符,描述游戏区域。用’#’表示石块,用’.’表示空的格子,

你的起始位置为’S’,箱子起始位置为’B’,箱子目标位置为’T’。

输入以R=C=0结束。

Output

对于第i组数据,如果不能将箱子推到指定格子,那么输出一行”Impossible.”(不含引号);否则,输出具有最少推动次数的操作序列。

如果有多个,则输出具有最少移动次数的操作序列。如果还有多个,输出任意一个即可。

操作序列是一行由’N’,’S’,’E’,’W’,’n’,’s’,’e’,w’组成的字符串,大写字母表示推动操作,小写字母表示移动操作,方向依次表示北,南,东,西。

这个题目轮玩的话可能都会玩,但是当初玩的时候可能不会去考虑用最少的步数去完成他,而是通过每一关就是完成任务了。

所以,就要重新审视这个题目了。

人要推着箱子将箱子推到目标处,其中隐含了很多必要条件的。首先箱子肯定到目标处有1条或多条路径;其次人到箱子的位置也有一条或多条路径,还有的就是在转弯处人能否箱子推过去。

这种情况虽然箱子到目标有路径,人到箱子也有路径,但是却是无法完成任务的。这个应该都很容易知道的。

那么解题思路是什么呢???双bfs即可

一个bfs就是搜索人朝着箱子的过程,当到达箱子的四周的某一个点时,再搜索人此刻推着箱子到目标位置的过程。如果最后成功的到达了目标,输出对应的最短的路径即可。如果所有的情况都搜索完也没到达,那么就是不可完成了。

  1 #include 
  2 #include 
  3 #include 
  4 #include 
  5 #include <string>
  6 #include 
  7 #include
  8 using namespace std;
  9
 10 struct Position // 位置类型
 11 {
 12     int r;
 13     int c;
 14     bool operator ==(const Position& rhs) const;
 15 };
 16
 17 bool Position::operator ==(const Position& rhs) const
 18 {
 19     return r == rhs.r && c == rhs.c;
 20 }
 21
 22 struct Box // 箱子状态
 23 {
 24     Position currPos; // 箱子的当前位置
 25     Position personPos; // 人的位置(人在箱子相邻的某一侧)
 26     string ans; // 箱子和人沿途走过的路径
 27 };
 28
 29 struct Person // 人的状态
 30 {
 31     Position currPos; // 人的位置
 32     string ans; // 人沿途走过的路径
 33 };
 34
 35 struct PushingBoxes // 解题类
 36 {
 37 protected:
 38     int m; // 地图行数
 39     int n; // 地图列数
 40     char** arr; // arr[i][j]表示第i行第j列是空地还是障碍物
 41     bool** vis; // vis[i][j]表示在搜索人走向箱子的过程中,(i,j)这个位置是否走到过
 42     bool*** mark; // mark[i][j][k]表示人推箱子的过程中,箱子沿着方向k到达位置(i,j),这个状态是否搜索过
 43     static Position dirs[4]; // 上下左右方向数组
 44     static char op[4]; // 方向对应的字符串,上北下南左西右东
 45     void GetMemory(); // 动态分配内存
 46     void ReleaseMemory(); // 动态释放内存
 47     bool InFreeSpace(const Position& pos) const; // 判断参数所表示的位置是否是可以到达的无障碍的位置
 48     bool BfsFromPersonToPos(const Position& personPos, const Position& boxPos, const Position& pos, string& path); // 搜索人朝位置pos移动的过程
 49     bool BfsFromBoxToTarget(const Position& personPos, const Position& boxPos, const Position& target, string& path); // 搜索箱子朝目标位置移动的过程
 50 public:
 51     void Solve();
 52 };
 53
 54 Position PushingBoxes::dirs[4] = { -1,0,1,0,0,-1,0,1 };//注意题目要求的是n、s、w、e的顺序
 55 char PushingBoxes::op[4] = { 'n','s','w','e' };//注意题目要求的是n、s、w、e的顺序
 56
 57 void PushingBoxes::GetMemory()
 58 {
 59     arr = new char*[m];
 60     for (int i = 0; i < m; i++)
 61     {
 62         arr[i] = new char[n];
 63     }
 64     vis = new bool*[m];
 65     for (int i = 0; i < m; i++)
 66     {
 67         vis[i] = new bool[n];
 68     }
 69     mark = new bool**[m];
 70     for (int i = 0; i < m; i++)
 71     {
 72         mark[i] = new bool*[n];
 73         for (int j = 0; j < n; j++)
 74         {
 75             mark[i][j] = new bool[4];
 76         }
 77     }
 78 }
 79
 80 void PushingBoxes::ReleaseMemory()
 81 {
 82     for (int i = 0; i < m; i++)
 83     {
 84         for (int j = 0; j < n; j++)
 85         {
 86             delete[] mark[i][j];
 87         }
 88         delete[] mark[i];
 89     }
 90     delete[] mark;
 91
 92     for (int i = 0; i < m; i++)
 93     {
 94         delete[] vis[i];
 95     }
 96     delete[] vis;
 97
 98     for (int i = 0; i < m; i++)
 99     {
100         delete[] arr[i];
101     }
102     delete[] arr;
103 }
104
105 bool PushingBoxes::InFreeSpace(const Position& pos) const
106 {
107     if (pos.r >= 0 && pos.r < m && pos.c >= 0 && pos.c < n)
108     {
109         if (arr[pos.r][pos.c] != '#')
110         {
111             return true;
112         }
113     }
114     return false;
115 }
116
117 // 搜索人朝位置pos移动的过程
118 bool PushingBoxes::BfsFromPersonToPos(const Position& personPos, const Position& boxPos, const Position& pos, string& path)
119 {
120     path = "";
121     if (!InFreeSpace(personPos) || !InFreeSpace(pos))
122     {
123         return false;
124     }
125     queue q;
126     Person currNode;
127     currNode.currPos = personPos;
128     currNode.ans = "";
129     for (int i = 0; i < m; i++)
130     {
131         fill(vis[i], vis[i] + n, false);
132     }
133     vis[boxPos.r][boxPos.c] = true; // 人不能和箱子重合,避免人走到箱子的位置
134     vis[currNode.currPos.r][currNode.currPos.c] = true;
135     q.push(currNode);
136     while (!q.empty())
137     {
138         currNode = q.front();
139         q.pop();
140         if (currNode.currPos == pos)
141         {
142             path = currNode.ans;
143             return true;
144         }
145         for (int i = 0; i < 4; i++)
146         {
147             Person nextNode;
148             nextNode.currPos.r = currNode.currPos.r + dirs[i].r;
149             nextNode.currPos.c = currNode.currPos.c + dirs[i].c;
150             nextNode.ans = currNode.ans + op[i];
151             if (InFreeSpace(nextNode.currPos) && !vis[nextNode.currPos.r][nextNode.currPos.c])
152             {
153                 vis[nextNode.currPos.r][nextNode.currPos.c] = true;
154                 q.push(nextNode);
155             }
156         }
157     }
158     return false;
159 }
160
161 // 搜索箱子朝目标位置移动的过程
162 bool PushingBoxes::BfsFromBoxToTarget(const Position& personPos, const Position& boxPos, const Position& target, string& path)
163 {
164     path = "";
165     if (!InFreeSpace(personPos) || !InFreeSpace(target))
166     {
167         return false;
168     }
169     for (int i = 0; i < m; i++)
170     {
171         for (int j = 0; j < n; j++)
172         {
173             fill(mark[i][j], mark[i][j] + 4, false);
174         }
175     }
176     Box currNode;
177     currNode.currPos = boxPos;
178     currNode.personPos = personPos;
179     currNode.ans = "";
180     queue q;
181     q.push(currNode);
182     while (!q.empty())
183     {
184         currNode = q.front();
185         q.pop();
186         if (currNode.currPos == target)
187         {
188             path = currNode.ans;
189             return true;
190         }
191         for (int i = 0; i < 4; i++) //盒子周围的四个方向
192         {
193             Box nextNode; // 计算下一个新位置
194             nextNode.currPos.r = currNode.currPos.r + dirs[i].r;
195             nextNode.currPos.c = currNode.currPos.c + dirs[i].c;
196             if (InFreeSpace(nextNode.currPos) && !mark[nextNode.currPos.r][nextNode.currPos.c][i])
197             {
198                 Position pos; // 人应该在反方向的位置
199                 pos.r = currNode.currPos.r - dirs[i].r;
200                 pos.c = currNode.currPos.c - dirs[i].c;
201                 if (BfsFromPersonToPos(currNode.personPos, currNode.currPos, pos, path)) // 如果人能到达反方向的位置
202                 {
203                     nextNode.ans = currNode.ans + path + (char)(op[i] - 'a' + 'A');
204                     nextNode.personPos = currNode.currPos;
205                     mark[nextNode.currPos.r][nextNode.currPos.c][i] = true;
206                     q.push(nextNode);
207                 }
208             }
209         }
210     }
211     return false;
212 }
213
214 void PushingBoxes::Solve()
215 {
216     int k = 0;
217     scanf("%d %d", &m, &n);
218     while (m > 0 && n > 0)
219     {
220         GetMemory();
221         Box box;
222         Person person;
223         Position target;
224         for (int i = 0; i < m; i++)
225         {
226             for (int j = 0; j < n; j++)
227             {
228                 scanf(" %c", &arr[i][j]);
229                 if (arr[i][j] == 'S')
230                 {
231                     person.currPos.r = i;
232                     person.currPos.c = j;
233                 }
234                 if (arr[i][j] == 'T')
235                 {
236                     target.r = i;
237                     target.c = j;
238                 }
239                 if (arr[i][j] == 'B')
240                 {
241                     box.currPos.r = i;
242                     box.currPos.c = j;
243                 }
244             }
245         }
246         string path;
247         bool flag = BfsFromBoxToTarget(person.currPos, box.currPos, target, path);
248         printf("Maze #%d\n", ++k);
249         if (flag)
250         {
251             printf("%s\n\n", path.c_str());
252         }
253         else
254         {
255             printf("Impossible.\n\n");
256         }
257         ReleaseMemory();
258         scanf("%d %d", &m, &n);
259     }
260 }
261
262 int main()
263 {
264     PushingBoxes obj;
265     obj.Solve();
266     return 0;
267 }

Original: https://www.cnblogs.com/ygsworld/p/11323837.html
Author: 回忆酿的甜
Title: POJ1475(Pushing Boxes)–bbffss

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/582136/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 音视频技术入门课 -01 如何从色彩格式、帧率等参数角度看视频图像?

    本文将从视频 / 图像的原始数据格式、视频逐行 / 隔行扫描、帧率、图像分辨率、色域等几方面入手,对视频基础知识做一个整体性的了解。 看视频时会看到很多图像,是由一个个像素点组成的…

    Linux 2023年6月7日
    0132
  • 删除数据库表中重复数据的方法

    一直使用Postgresql数据库,有一张表是这样的: DROP TABLE IF EXISTS "public"."devicedata"…

    Linux 2023年6月6日
    096
  • ssh 或 putty 连接linux报错解决方法

    由于当天多次输入错误密码,ssh和putty就连接不上了,纠结了很久解决问题 ssh连接提示错误:server unexpectedly closed network connec…

    Linux 2023年6月13日
    098
  • 排序算法

    内部排序 这里先介绍一个概念,算法稳定性 算法稳定性 — 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]…

    Linux 2023年6月6日
    0133
  • Laxcus远程终端

    Laxcus集群操作系统的远程终端越来越象Linux的VIM了,除了界面风格之外,在用户使用的命令上也在向VIM靠近,原因嘛也不难理解,毕竟Laxcus是一个分布式的操作系统,处理…

    Linux 2023年6月6日
    0114
  • K8s-小型综合实验(k8s+keeplived+nginx+iptables)

    K8S小型综合实验(k8s+keeplived+nginx+iptables) 实验目的 1.Kubernetes 区域可采用 Kubeadm 方式进行安装。 2.要求在 Kube…

    Linux 2023年6月13日
    0109
  • 环境变量

    环境变量,简单来说就是描述程序执行环境的一组变量。 1、什么程序执行环境? 环境已经基础词汇呢,我们通常都用环境去解释别的词,想一下,日常生活怎么用环境。你到一个新地方,我问你环境…

    Linux 2023年6月6日
    0120
  • 【C++基础】函数的分文件编写

    cpp函数的分文件编写 作用:让代码结构更加清晰 如下步骤: 创建后缀名为.h的头文件 创建后缀名为.cpp的源文件 在头文件中写函数的声明 在源文件中写函数的定义,同时引入自定义…

    Linux 2023年6月13日
    0104
  • shell相关知识2

    <li class="tool-item tool-active is-like tool-clicked"><a href="ja…

    Linux 2023年5月28日
    080
  • 在linux中使用tcpdump抓包的方法:

    在linux中使用tcpdump抓包的方法: 1,运行下面命令来从所有网卡中捕获数据包: tcpdump -i any 2,从指定网卡中捕获数据包 tcpdump -i eth0 …

    Linux 2023年5月27日
    0120
  • zookeeper与kafka集群部署实现

    安装java依赖环境 配置zookeeper 启动zookeeper 检查状态 Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。该项目的目…

    Linux 2023年6月7日
    0190
  • PYTORCH: 60分钟 | 训练一个分类器

    你已经知道怎样定义神经网络,计算损失和更新网络权重。现在你可能会想, 那么,数据呢? 通常,当你需要解决有关图像、文本或音频数据的问题,你可以使用python标准库加载数据并转换为…

    Linux 2023年6月16日
    0194
  • 搭建docker镜像仓库(一):使用registry搭建本地镜像仓库

    服务器版本 docker软件版本 CPU架构 CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 x86_64…

    Linux 2023年6月7日
    086
  • 兼容各种浏览器的上下滚动代码

    直接切入正题 红色的表示为要注意统一的。 蓝色是表示要更改的。 内容高度一定要大于box1的高度否则不会滚动,本框架用的是phpcms,大家可根据自己的框架更改循环。 | {pc:…

    Linux 2023年6月13日
    087
  • mysql order by语句流程是怎么样的

    order by流程是怎么样的 注意点: select id, name,age,city from t1 where city=’&#x676D;&#x5DDE;…

    Linux 2023年6月8日
    0112
  • 画图3D Paint 3D工作区黑屏

    最近不知道画图3D抽什么风,黑屏了。 后来研究很久,发现这货竟然是用独立显卡,集显带不起来。 解决方案是在Nvidia控制面板给他分配独立显卡,不要使用集显,不要使用集显,不要使用…

    Linux 2023年6月13日
    0114
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球