POJ1475(Pushing Boxes)--bbffss
Posted ygsworld
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 <iostream> 2 #include <cmath> 3 #include <queue> 4 #include <cstdio> 5 #include <string> 6 #include <algorithm> 7 #include<functional> 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<Person> 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<Box> 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
以上是关于POJ1475(Pushing Boxes)--bbffss的主要内容,如果未能解决你的问题,请参考以下文章