【POJ】3523 The Morning after Halloween

1. 题目描述
$m \times n$的迷宫(最大为$16 \times 16$)包含最多3个点,这些点可以同时向相邻方向移动或保持停止,使用小写字母表示起始位置,使用大写字母表示中止位置。求最少经过多少时间,这些点可以从起始位置移动到对应的终止位置。

2. 基本思路
这是很经典的路径搜索问题,一般采用BFS。因为题目说每个$2 \times 2$个子矩阵,都至少有一个点为#,那么起始空白可走的点一定很少,因此,可以预处理这些点可以通过1个时间单位到达的有效位置。这样可以降低$5^3$的总排列。显然,同时对三个点组成的三元组进行状态压缩,这里采用移位。这些做完了,普通的BFS+map就已经可以解出正确解了。但是太慢了。因此,使用双向BFS+map,发现还是超时,原因是map太慢了(而且会随着状态的增加越来越慢)。那么,直接用数组存(注意不要MLE)。直接过了。双向BFS明显地提高了性能。

3. 代码

  1 /* 3523 */
  2 #include <iostream>
  3 #include <sstream>
  4 #include <string>
  5 #include <map>
  6 #include <queue>
  7 #include <set>
  8 #include <stack>
  9 #include <vector>
 10 #include <deque>
 11 #include <bitset>
 12 #include <algorithm>
 13 #include <cstdio>
 14 #include <cmath>
 15 #include <ctime>
 16 #include <cstring>
 17 #include <climits>
 18 #include <cctype>
 19 #include <cassert>
 20 #include <functional>
 21 #include <iterator>
 22 #include <iomanip>
 23 using namespace std;
 24 //#pragma comment(linker,"/STACK:102400000,1024000")
 25 
 26 #define sti                set<int>
 27 #define stpii            set<pair<int, int> >
 28 #define mpii            map<int,int>
 29 #define vi                vector<int>
 30 #define pii                pair<int,int>
 31 #define vpii            vector<pair<int,int> >
 32 #define rep(i, a, n)     for (int i=a;i<n;++i)
 33 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
 34 #define clr                clear
 35 #define pb                 push_back
 36 #define mp                 make_pair
 37 #define fir                first
 38 #define sec                second
 39 #define all(x)             (x).begin(),(x).end()
 40 #define SZ(x)             ((int)(x).size())
 41 #define lson            l, mid, rt<<1
 42 #define rson            mid+1, r, rt<<1|1
 43 #define INF                0x3f3f3f3f
 44 #define mset(a, val)    memset(a, (val), sizeof(a))
 45 
 46 const int maxn = 20;
 47 const int maxm = 150;
 48 int ID[maxn][maxn];
 49 int sz[maxm];
 50 int Move[maxm][5];
 51 int visit[2][maxm][maxm][maxm];
 52 char s[maxn][maxn];
 53 map<char,int> ptb;
 54 queue<int> Q[2];
 55 int dir[5][2] = {
 56     -1, 0, 1, 0, 0, -1, 0, 1, 0,0
 57 };
 58 int n, m, gn;
 59 int st, ed;
 60 
 61 inline bool judge(int x, int y) {
 62     return x<0 || x>=n || y<0 || y>=m || s[x][y]=='#';
 63 }
 64 
 65 void init() {
 66     int cnt = 0;
 67     map<char,int>::iterator iter;
 68     
 69     ptb.clr();
 70     
 71     rep(i, 0, n) {
 72         rep(j, 0, m) {
 73             if (s[i][j] == '#')
 74                 continue;
 75             
 76             ID[i][j] = cnt++;
 77             if (s[i][j] != ' ')
 78                 ptb[s[i][j]] = ID[i][j];
 79         }
 80     }
 81     
 82     rep(i, 0, n) {
 83         rep(j, 0, m) {
 84             if (s[i][j] == '#')
 85                 continue;
 86             
 87             const int& id = ID[i][j];
 88             sz[id] = 1;
 89             Move[id][0] = id;
 90             rep(k, 0, 4) {
 91                 int x = i + dir[k][0];
 92                 int y = j + dir[k][1];
 93                 if (judge(x, y))
 94                     continue;
 95                 
 96                 Move[id][sz[id]++] = ID[x][y];
 97             }
 98         }
 99     }
100     
101     st = ed = 0;
102     
103     for (char ch='a'; ch<='z'; ++ch) {
104         iter = ptb.find(ch);
105         if (iter != ptb.end()) {
106             st = (st << 8) | iter->sec;
107             iter = ptb.find(ch-'a'+'A');
108             #ifndef ONLINE_JUDGE
109             assert(iter != ptb.end());
110             #endif
111             ed = (ed << 8) | iter->sec;
112         }
113     }
114 }
115 
116 int bfs1(const int qid) {
117     int cst, nst;
118     int qsz = SZ(Q[qid]);
119     
120     while (qsz--) {
121         cst = Q[qid].front();
122         Q[qid].pop();
123         
124         int step = visit[qid][0][0][cst] + 1;
125         rep(i, 0, sz[cst]) {
126             nst = Move[cst][i];
127             if (visit[qid][0][0][nst] == -1) {
128                 if (visit[qid^1][0][0][nst] >= 0)
129                     return step + visit[qid^1][0][0][nst];
130                 visit[qid][0][0][nst] = step;
131                 Q[qid].push(nst);
132             }
133         }
134     }
135     
136     return -1;
137 }
138 
139 int bfs2(const int qid) {
140     int cst[2], nst[2], tmp;
141     int qsz = SZ(Q[qid]);
142     
143     while (qsz--) {
144         st = Q[qid].front();
145         Q[qid].pop();
146         
147         per(i, 0, 2) {
148             cst[i] = st & 0xff;
149             st >>= 8;
150         }
151         
152         int step = visit[qid][0][cst[0]][cst[1]] + 1;
153         
154         rep(i, 0, sz[cst[0]]) {
155             nst[0] = Move[cst[0]][i];
156             rep(j, 0, sz[cst[1]]) {
157                 nst[1] = Move[cst[1]][j];
158                 if (nst[0]==nst[1] || (nst[0]==cst[1]&&nst[1]==cst[0]))
159                     continue;
160                 
161                 tmp = nst[0]<<8 | nst[1];
162                 if (visit[qid][0][nst[0]][nst[1]] == -1) {
163                     if (visit[qid^1][0][nst[0]][nst[1]] != -1)
164                         return step + visit[qid^1][0][nst[0]][nst[1]];
165                     visit[qid][0][nst[0]][nst[1]] = step;
166                     Q[qid].push(tmp);
167                 }
168             }
169         }
170     }
171     
172     return -1;
173 }
174 
175 inline bool check(int *nst, int *cst) {
176     return (nst[0]==cst[1] && nst[1]==cst[0]) || (nst[0]==cst[2] && nst[2]==cst[0]) || (nst[1]==cst[2] && nst[2]==cst[1]);
177 }
178 
179 int bfs3(const int qid) {
180     int cst[3], nst[3], tmp;
181     int qsz = SZ(Q[qid]);
182     
183     while (qsz--) {
184         st = Q[qid].front();
185         Q[qid].pop();
186         
187         per(i, 0, 3) {
188             cst[i] = st & 0xff;
189             st >>= 8;
190         }
191         
192         int step = visit[qid][cst[0]][cst[1]][cst[2]] + 1;
193         
194         rep(i, 0, sz[cst[0]]) {
195             nst[0] = Move[cst[0]][i];
196             rep(j, 0, sz[cst[1]]) {
197                 nst[1] = Move[cst[1]][j];
198                 rep(k, 0, sz[cst[2]]) {
199                     nst[2] = Move[cst[2]][k];
200                     if (nst[0]==nst[1] || nst[1]==nst[2] || nst[0]==nst[2] || check(cst, nst))
201                         continue;
202                     
203                     tmp = (nst[0]<<16) | (nst[1]<<8) | (nst[2]);
204                     
205                     if (visit[qid][nst[0]][nst[1]][nst[2]] == -1) {
206                         if (visit[qid^1][nst[0]][nst[1]][nst[2]] != -1)
207                             return step + visit[qid^1][nst[0]][nst[1]][nst[2]];
208                         visit[qid][nst[0]][nst[1]][nst[2]] = step;
209                         Q[qid].push(tmp);
210                     }
211                 }
212             }
213         }
214     }
215     
216     return -1;
217 }
218 
219 #define bibfs(n)\
220 int bibfs##n() {\
221     int tmp;    \
222                 \
223     while (!Q[0].empty() || !Q[1].empty()) {\
224         tmp = bfs##n(0);\
225         if (tmp >= 0)    return tmp;\
226         tmp = bfs##n(1);\
227         if (tmp >= 0)    return tmp;\
228     }\
229                 \
230     return -1;\
231 }
232 
233 #define callbibfs(n) bibfs##n()
234 
235 bibfs(1)
236 bibfs(2)
237 bibfs(3)
238 
239 void solve() {
240     init();
241     int ans;
242     
243     memset(visit, -1, sizeof(visit));
244     rep(i, 0, 2)
245         while (!Q[i].empty()) Q[i].pop();
246     visit[0][st>>16][(st>>8)&0xff][st&0xff] = 0;
247     visit[1][ed>>16][(ed>>8)&0xff][ed&0xff] = 0;
248     Q[0].push(st);
249     Q[1].push(ed);
250     
251     if (gn == 1) {
252         ans = callbibfs(1);
253     } else if (gn == 2) {
254         ans = callbibfs(2);
255     } else {
256         ans = callbibfs(3);
257     }
258     
259     printf("%d\n", ans);
260 }
261 
262 int main() {
263     ios::sync_with_stdio(false);
264     #ifndef ONLINE_JUDGE
265         freopen("data.in", "r", stdin);
266         freopen("data.out", "w", stdout);
267     #endif
268     
269     while (scanf("%d%d%d%*c",&m,&n,&gn)!=EOF && (n||m||gn)) {
270         rep(i, 0, n)
271             gets(s[i]);
272         solve();
273     }
274     
275     #ifndef ONLINE_JUDGE
276         printf("time = %d.\n", (int)clock());
277     #endif
278     
279     return 0;
280 }

 

posted on 2016-03-23 23:18  Bombe  阅读(569)  评论(0编辑  收藏  举报

导航