CF585B
题意
一个跑酷游戏,每一回合玩家先向前跑一步,然后允许向上一格、向下一格和不动,然后火车前进两步。如果撞到火车则游戏失败,如果玩家成功跑到了地图的最右边,则游戏胜利。现在告诉你场上的情况,问你玩家是否可以成功。
分析
首先很容易想到使用 bfs,因为在这里有拐弯这一个操作,这一处会使得可能的方案数不止一种,为了遍历所有可能的方案我们使用 bfs。
然后我们发现火车向左移两步和玩家再向右移两步相同,所以我们让火车不移动,毕竟玩家移动比火车移动要简单很多。玩家在此时额外向前跑两步而不是火车移动。则整个回合内玩家操作如下:
- 前进一步
- 向上一步,向下一步,或不动
- 前进两步
期间任何一步操作中若玩家移动路径上的方块上有火车,则此方案不合法。
详情见代码。
代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> node;
int train[3][105];
bool visit[3][105];
int n, k;
queue<node> que;
bool bfs(int tx, int ty) {
memset(visit, 0, sizeof(visit));
while (!que.empty())
que.pop();
que.push((node){tx, ty}); //起点
while (!que.empty()) {
node cac = que.front();
que.pop();
int &x = cac.first, &y = cac.second;
if (visit[x][y])
continue;
visit[x][y] = true;
if (y >= n - 1) //跑出地图,即成功
return true;
if (train[x][++y]) //1.前进一格
continue;
if (y == n - 1) //跑出地图,即成功
return true;
for (int i = -1; i < 2; i++) { //2.尝试转向
int tx = x + i;
if (tx < 0 || tx > 2)
continue;
if (train[tx][y] || train[tx][y + 1] || train[tx][y + 2])
continue; //3.前进两格
que.push((node){tx, y + 2});
}
}
return false;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
memset(train, 0, sizeof(train));
scanf("%d%d", &n, &k);
int start_x = 1, start_y = 0; //起始位置
for (int i = 0; i < 3; i++) {
for (int j = 0; j < n; j++) {
char c = getchar();
while (c == ' ' || c == '\n' || c == '\r')
c = getchar();
train[i][j] = c != '.';
if (c == 's')
start_x = i, start_y = j;
}
}
if (bfs(start_x, start_y))
puts("YES");
else
puts("NO");
}
return 0;
}