poj 1475 推箱子

bfs是一层层的遍历下去,每多一层即为多走一步,因此只要遇到T就停,此时肯定是最小步数。

所以这两层bfs应为,先对箱子的最少步数进行bfs,从而求出推箱子所用最少步数;

然后箱子bfs内部嵌入人的bfs,从而箱子每走一步,判断一下这个移动能否由人来完成(由箱子的移动倒推人应该在的位置,看这个位置是否合理)。

一、http://tech.artyoo.me/?p=282

  1 #include <map>
  2 #include <set>
  3 #include <queue>
  4 #include <stack>
  5 #include <math.h>
  6 #include <time.h>
  7 #include <stdio.h>
  8 #include <stdlib.h>
  9 #include <iostream>
 10 #include <limits.h>
 11 #include <string.h>
 12 #include <string>
 13 #include <algorithm>
 14 #include <iomanip>
 15 #define read freopen("in.txt","r",stdin)  
 16 #define write freopen("out.txt","w",stdout) 
 17 using namespace std;
 18 #define MAXSIZE 22
 19 typedef struct {
 20     int bx, by, px, py;
 21     string path;
 22 } Node;
 23 typedef struct {
 24     int x, y;
 25     string path;    
 26 } Point;
 27 int row, col;
 28 char grid[MAXSIZE][MAXSIZE];
 29 bool vis[MAXSIZE][MAXSIZE][4], vis2[MAXSIZE][MAXSIZE];
 30 Node st;
 31 int caseID;
 32 queue<Node> qb;
 33 queue<Point> qp;
 34  
 35 const int dx[] = {-1, 1, 0, 0};
 36 const int dy[] = {0, 0, -1, 1};
 37 const char Dir[] = {'N', 'S', 'W', 'E'};
 38 const char dir[] = {'n', 's', 'w', 'e'};
 39 string person_path;
 40  
 41 int Min(int a,int b){return a<b?a:b;}
 42 int Max(int a,int b){return a>b?a:b;}
 43  
 44 bool bfs_person(Point sp, Point ep, int bx, int by) {
 45     person_path = "";
 46     memset(vis2, false, sizeof(vis2));
 47     while(!qp.empty()) qp.pop();
 48     sp.path = "";
 49     qp.push(sp);
 50     vis2[sp.x][sp.y] = true;
 51     while(!qp.empty()) {
 52         Point now = qp.front(); qp.pop();
 53         if(now.x == ep.x && now.y == ep.y) {
 54             person_path = now.path;
 55             return true;
 56         }
 57         for(int d = 0; d < 4; d++) {
 58             int x = now.x + dx[d];
 59             int y = now.y + dy[d];
 60             if(x >= 0 && x < row && y >= 0 && y < col && grid[x][y] != '#' && !(x == bx && y == by)) {
 61                 if(!vis2[x][y]) {
 62                     Point next;
 63                     next.x = x;
 64                     next.y = y;
 65                     next.path = now.path + dir[d];
 66                     qp.push(next);
 67                     vis2[x][y] = true;  
 68                 }  
 69             }
 70         }
 71     }
 72     return false;
 73 }
 74  
 75 string bfs_box() {
 76     memset(vis, false, sizeof(vis));
 77     while(!qb.empty()) qb.pop();
 78     qb.push(st);
 79     while(!qb.empty()) {
 80         Node now;
 81         now = qb.front(); qb.pop();
 82         if(grid[now.bx][now.by] == 'T') {
 83             return now.path;    
 84         }
 85         for(int d = 0; d < 4; d++) {
 86             int x = now.bx + dx[d];
 87             int y = now.by + dy[d];
 88             if(x >= 0 && x < row && y >= 0 && y < col && grid[x][y] != '#') {
 89                 if(!vis[x][y][d]) {
 90                     Point sp, ep; /* sp: 人的当前位置;ep:人要按当前方向推箱子的话必须得到达的位置 */
 91                     sp.x = now.px;  sp.y = now.py;
 92                     ep.x = now.bx;  ep.y = now.by;
 93                     switch(d) {
 94                         case 0: ep.x += 1; break;
 95                         case 1: ep.x -= 1; break;
 96                         case 2: ep.y += 1; break;
 97                         case 3: ep.y -= 1; break; 
 98                     }
 99                     if(ep.x >= 0 && ep.x < row && ep.y >= 0 && ep.y < col && grid[ep.x][ep.y] != '#') {            
100                         if(bfs_person(sp, ep, now.bx, now.by)) {
101                             Node next;
102                             next.bx = x;  next.by = y;
103                             next.px = now.bx;  next.py = now.by;
104                             next.path = now.path + person_path + Dir[d];
105                             qb.push(next);
106                             vis[x][y][d] = true;
107                         }
108                     }
109                 }
110             }
111         }
112     }
113     return "Impossible.";
114 }
115  
116 int main() {
117     read; write;
118     caseID = 0;
119     while(scanf("%d%d", &row, &col) && row && col) {
120         getchar();
121         for(int i = 0; i < row; i++) {
122             gets(grid[i]);
123         }
124         for(int i = 0; i < row; i++) {
125             for(int j = 0; j < col; j++) {
126                 if(grid[i][j] == 'B') {
127                     st.bx = i;
128                     st.by = j;
129                     grid[i][j] = '.';
130                 } else if(grid[i][j] == 'S') {
131                     st.px = i;
132                     st.py = j;
133                     grid[i][j] = '.';
134                 }
135             }
136         }
137         st.path = "";
138         printf("Maze #%d\n", ++caseID);
139         cout << bfs_box() << endl << endl;
140     }
141     return 0;
142 }

 

二、http://www.cnblogs.com/Missa/archive/2012/10/07/2714435.html

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <queue>
  6 #include <string>
  7 
  8 using namespace std;
  9 
 10 #define MAXN 22
 11 char P[4] = { 'N', 'S', 'W', 'E' };
 12 char M[4] = { 'n', 's', 'w', 'e' };
 13 int R, C;
 14 int dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 };//之前当成坐标轴里x,y坐标来算,怎么都不对。后来发现原来x,y是行数和列数。x-1代表到上一行去,即N。
 15 char map[MAXN][MAXN];
 16 struct point
 17 {
 18     int x, y;
 19     int p_x, p_y;//当前状态person所在的地方
 20     string ans;
 21 };
 22 bool isok(int x, int y)
 23 {
 24     if (x >= 0 && x < R && y >= 0 && y < C && map[x][y] != '#')
 25         return true;
 26     return false;
 27 }
 28 string tmp;
 29 bool bfs_person(point en, point cu)
 30 {
 31     tmp = "";
 32     point st;
 33     st.x = en.p_x;
 34     st.y = en.p_y;
 35     st.ans = "";
 36     queue<point>q;
 37     bool vis[MAXN][MAXN];
 38     memset(vis, 0, sizeof(vis));
 39     while (!q.empty())
 40         q.pop();
 41     q.push(st);
 42     while (!q.empty())
 43     {
 44         point cur, next;
 45         cur = q.front();
 46         q.pop();
 47         if (cur.x == en.x && cur.y == en.y)
 48         {
 49             tmp = cur.ans;
 50             return true;
 51         }
 52         for (int i = 0; i < 4; i++)
 53         {
 54             next = cur;
 55             next.x = cur.x + dir[i][0];
 56             next.y = cur.y + dir[i][1];
 57             if (!isok(next.x, next.y)) continue;
 58             if (next.x == cu.x && next.y == cu.y) continue;//cu.x,cu.y is the location of the box.
 59             if (vis[next.x][next.y]) continue;//来过的地方就不能在来了???????莫非bfs都是这样?
 60             vis[next.x][next.y] = 1;
 61             next.ans = cur.ans + M[i];
 62             //cout << "M[i] "<<M[i] << endl;
 63             //cout << "cur.ans " << cur.ans << endl;
 64             q.push(next);
 65         }
 66     }
 67     return false;
 68 }
 69 string bfs_box()
 70 {
 71     bool vis[MAXN][MAXN][4];//某点四个方向是否访问!!0==N,1==S,2==W,3==E
 72     point st;
 73     st.x = st.y = -1;
 74     st.p_x = st.p_y = -1;
 75     st.ans = "";
 76     for (int i = 0; i < R && (st.x == -1 || st.p_x == -1); i++)
 77     for (int j = 0; j < C && (st.x == -1 || st.p_x == -1); j++)
 78     if (map[i][j] == 'B')
 79     {
 80         st.x = i;
 81         st.y = j;
 82         map[i][j] = '.';
 83     }
 84     else if (map[i][j] == 'S')
 85     {
 86         st.p_x = i;
 87         st.p_y = j;
 88         map[i][j] = '.';
 89     }
 90     //----------------------------------------
 91     //cout<<"st.x="<<st.x<<" st.y="<<st.y<<" st.p_x="<<st.p_x<<" st.p_y="<<st.p_y<<endl;
 92     //----------------------------------------
 93     queue<point> q;
 94     while (!q.empty())
 95         q.pop();
 96     q.push(st);
 97     memset(vis, 0, sizeof(vis));
 98     while (!q.empty())
 99     {
100         point cur = q.front(); q.pop();
101         //----------------------------------------
102         //        cout<<"cur.x="<<cur.x<<" cur.y="<<cur.y<<" cur.p_x="<<cur.p_x<<" cur.p_y="<<cur.p_y<<endl;
103         //    cout<<"-----------------------------\n";
104         //----------------------------------------
105         point next, pre;
106         if (map[cur.x][cur.y] == 'T')
107             return cur.ans;
108         for (int i = 0; i < 4; i++)
109         {
110             next = cur;
111             next.x = cur.x + dir[i][0];
112             next.y = cur.y + dir[i][1];
113             if (!isok(next.x, next.y))
114                 continue;
115             if (vis[next.x][next.y][i])
116                 continue;
117             pre = cur;
118             switch (i)
119             {
120             case 0: pre.x = cur.x + 1; break;
121             case 1: pre.x = cur.x - 1; break;
122             case 2: pre.y = cur.y + 1; break;
123             case 3: pre.y = cur.y - 1; break;
124             }
125             if (!bfs_person(pre, cur))//搜寻人是否能走到特定的位置
126                 continue;
127             vis[next.x][next.y][i] = 1;
128             next.ans = cur.ans + tmp;
129             next.ans = next.ans + P[i];
130             cout << "P[i] " << P[i] << endl;
131             cout <<"cur--"<< cur.x << "," << cur.y << ";" << cur.p_x << "," << cur.p_y << endl;
132             cout <<"next--" << next.x << "," << next.y << ";" << next.p_x << "," << next.p_y << endl;
133             next.p_x = cur.x; next.p_y = cur.y;
134             q.push(next);
135         }
136     }
137     return "Impossible.";
138 }
139 
140 int main()
141 {
142     int cas = 1;
143     while (scanf("%d%d", &R, &C) && (R + C))
144     {
145         getchar();
146         for (int i = 0; i < R; i++)
147             gets(map[i]);
148 
149         //---------------------------------------
150         //    for(int i=0;i<R;i++)
151         //    cout<<map[i]<<endl;
152         //----------------------------------------
153 
154         printf("Maze #%d\n", cas++);
155         //printf("%s\n",bfs_box());
156         cout << bfs_box() << endl << endl;
157     }
158     return 0;
159 }

 

转载于:https://www.cnblogs.com/forcheryl/p/4411056.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值