题意:map中给出小偷的位置,警察的位置。警察有一只狗,开始的时候警察和狗一起行动,也就是看做一个格子,当警察遇见小偷走过的格子时,狗就会嗅到它的气味,以2倍的速度追捕小偷。现在,小偷希望知道自己是否有安全路线逃出去,以此决定是否要继续拿着偷的东西。出口不止一处,只有一个警察和一只狗,一个小偷。【知道也才不告诉他,哼。】
思路:因为小偷每走到一个格子时,时间为t1,决定他是否被抓到的因素是警察到这里的时间t2。当t1>=t2时,小偷被抓,当t1<t2时,小偷还能从该点继续走,直到t2-t1+t2时刻被狗抓住或者跑出去。所以首先对警察bfs,确定警察到map上的每个格子最短时间t2。然后,对小偷bfs,判断当前点是否能走的条件:map范围内且不是围墙 && 到达时间t1<t2 && 还没有到限制的时间 && (没有走过 || 之前走到当前路线的时间比现在小)。注意:我们每到一个新的点,当前点的限制是前一个点的限制和当前点计算得到的限制的max值,而我们可以选择一条路线使得再次到达当前点的步数更小,获得的逃跑时间更长。
【事实证明:"之前走到当前路线的时间比现在小"条件可以去掉,因为本题中 任何位置bfs第一次搜索到的时间,一定是最短时间。】
代码:
#include <stdio.h> #include <string.h> #include <iostream> #include <math.h> #define maxn 210 #define inf 0x7f7f7f7f using namespace std; int step[maxn][maxn]; char mp[maxn][maxn]; int vis[maxn][maxn]; // lim int dir[4][2] = {1,0, -1,0, 0,1, 0,-1}; int w, h; struct Node { int x, y, lim, step; Node () { lim = inf; step = inf; } }q[maxn*maxn*maxn], st; struct Point{ int x, y; }que[maxn*maxn*maxn], now, nxt, temp; bool check(int x, int y) { if (x>=0 && x<h && y>=0 && y<w && mp[x][y] != 'X') return true; return false; } void bfs_police(int px, int py){ memset(vis, 0, sizeof(vis)); vis[px][py] = 1; step[px][py] = 0; now.x = px, now.y = py; int head = 0, tail = -1; que[++tail] = now; while(head <= tail) { now = que[head++]; for (int i=0; i<4; ++i) { nxt.x = now.x + dir[i][0]; nxt.y = now.y + dir[i][1]; if (check(nxt.x, nxt.y) && vis[nxt.x][nxt.y] == 0) { step[nxt.x][nxt.y] = step[now.x][now.y] + 1; vis[nxt.x][nxt.y] = 1; que[++tail] = nxt; } } } } bool bfs_thief(Node st) { memset(vis, 0, sizeof(vis)); st.step = 0; st.lim = (step[st.x][st.y] - st.step) + step[st.x][st.y]; int head = 0, tail = -1; q[++tail] = st; vis[st.x][st.y] = st.lim; while(head <= tail) { Node now = q[head++]; if (mp[now.x][now.y] == 'E') { return true; } for (int i=0; i<4; ++i) { Node nxt = now; nxt.x += dir[i][0]; nxt.y += dir[i][1]; nxt.step++; if (check(nxt.x, nxt.y)) { int lim = step[nxt.x][nxt.y] + (step[nxt.x][nxt.y] - nxt.step); if (lim < nxt.lim) nxt.lim = lim; if (nxt.step < step[nxt.x][nxt.y] && nxt.step < nxt.lim && (vis[nxt.x][nxt.y] == 0 || nxt.lim > vis[nxt.x][nxt.y])) { vis[nxt.x][nxt.y] = nxt.lim; q[++tail] = nxt; } } } } return false; } int main() { //freopen("in.cpp", "r", stdin); while(~scanf("%d%d", &w, &h)) { if (w<3 || h<3) break; getchar(); int px, py; for (int i=0; i<h; ++i) { gets(mp[i]); int len = strlen(mp[i]); for (int j=0; j<len; ++j) { if (mp[i][j] == 'K') { px = i, py = j; } else if (mp[i][j] == 'T') { st.x = i, st.y = j; } } } bfs_police(px, py); bool esc = bfs_thief(st); if (esc) printf("KEEP IT\n"); else printf("DROP IT\n"); } return 0; }