zoukankan      html  css  js  c++  java
  • 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
    ", ++k);
    249         if (flag)
    250         {
    251             printf("%s
    
    ", path.c_str());
    252         }
    253         else
    254         {
    255             printf("Impossible.
    
    ");
    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 }
  • 相关阅读:
    线段树 hdu3255 Farming
    3.CCFadeOutTRTiles,部落格效果,跳动的方块特效,3D瓷砖晃动特效,破碎的3D瓷砖特效,瓷砖洗牌特效,分多行消失特效,分多列消失特效
    分析:新建短信,当我们接受人RecipientsEditor中输入+86的时候,系统会自己主动在+86后增加空格
    【POJ3377】Ferry Lanes 最短路
    Please ensure that adb is correctly located at &#39;D:Androidandroid-sdkplatform-toolsadb.exe&#39; and
    Objective-C
    分布式高维空间近邻搜索项目开发
    我的改进版2048(2)
    github关联域名,创建个人站点教程终结篇
    数据结构(6)二叉树
  • 原文地址:https://www.cnblogs.com/ygsworld/p/11323837.html
Copyright © 2011-2022 走看看