【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 }