题目大意:
就是现在有一个H*W的地图, H, W <= 1000, 要从S的位置到E的位置, 每次进行的操作要么是向左或者右转, 要么是向前走, 现在给出一个只有旋转的序列(只有L, R, 没有向前走的F), 现在在这个序列的任意位置加入任意数量的F问是否可以成为一个从S到达E的指令序列
大致思路:
考虑到到达位置(x, y)面朝方向为d的序列一定是在那个LR位置尽量靠前的位置更优, bfs的时候的状态只有H*W*4种
那么处理出每个LR序列的位置i到下一次面朝位置为d的对应LR序列位置为next[i][d]即可
代码如下:
Result : Accepted Memory : 86780 KB Time : 951 ms
/* * Author: Gatevin * Created Time: 2015/8/10 13:48:42 * File Name: Sakura_Chiyo.cpp */ #include<iostream> #include<sstream> #include<fstream> #include<vector> #include<list> #include<deque> #include<queue> #include<stack> #include<map> #include<set> #include<bitset> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<cmath> #include<ctime> #include<iomanip> using namespace std; const double eps(1e-8); typedef long long lint; /* * 考虑到对于到达位置(x, y)朝向为d, 到达当前序列为第k个的情况, 一定比(x, y, d)且k2 > k的情况要优 * 所以在惊醒bfs的时候要遍历的状态只有[x][y][d]一共H*W*4种 * 由于优的是k2 > k的情况需要按照给出的LR的序列从前向后来进行bfs * 这里我图方便直接开了N个队列MLE了...于是换了邻接表来存储... * 为了转移的方便需要处理出对于给出的LR的序列当前在第i个, 要转到面朝特定方向时接下来需要转到序列中的哪个L或R才能行 */ int dx[] = {-1, 0, 1, 0}; int dy[] = {0, 1, 0, -1}; int H, W, N; #define next nex char lr[1000100];// int next[1000100][4]; int dir[1000100]; const int inf = 1e9 + 7; char maz[1010][1010]; int vis[1010][1010][4]; int sx, sy, ex, ey; #define mp make_pair int cas; int tot;//邻接表边数 struct Edge//queue MLE了换邻接表上 { int x, y, nex; }; Edge edge[4000010]; int head[1000010]; void addEdge(int s, int x, int y) { edge[tot].x = x, edge[tot].y = y; edge[tot].nex = head[s]; head[s] = tot++; } bool bfs() { //Q[0].push(mp(sx, sy)); memset(head, -1, sizeof(head)); tot = 0; while(sx >= 0 && sx < H && sy >= 0 && sy < W && vis[sx][sy][0] != cas && maz[sx][sy] != '#') { //Q[0].push(mp(sx, sy)); addEdge(0, sx, sy); vis[sx][sy][0] = cas; if(sx == ex && sy == ey) return true; sx += dx[0], sy += dy[0]; } for(int i = 0; i <= N; i++) { //while(!Q[i].empty()) for(int j = head[i]; j + 1; j = edge[j].nex) { //int nx = Q[i].front().first, ny = Q[i].front().second; int nx = edge[j].x, ny = edge[j].y; //Q[i].pop(); for(int d = 0; d < 4; d++) { if(next[i][d] == inf) continue; int tx = nx + dx[d], ty = ny + dy[d]; while(tx >= 0 && tx < H && ty >= 0 && ty < W && vis[tx][ty][d] != cas && maz[tx][ty] != '#') { //Q[next[i][d]].push(mp(tx, ty)); addEdge(next[i][d], tx, ty); vis[tx][ty][d] = cas; if(tx == ex && ty == ey) return true; tx += dx[d], ty += dy[d]; } } } } return false; } void init() { dir[0] = 0; for(int i = 0; i < N; i++) dir[i + 1] = (lr[i] == 'L') ? (dir[i] + 3) % 4 : (dir[i] + 1) % 4; int last[4] = {inf, inf, inf, inf}; for(int i = N; i >= 0; i--) { for(int j = 0; j < 4; j++) next[i][j] = last[j]; last[dir[i]] = i; } return; } int main() { cas = 0; memset(vis, 0, sizeof(vis)); while(~scanf("%d %d %d", &H, &W, &N)) { cas++; scanf("%s", lr); init(); for(int i = 0; i < H; i++) { scanf("%s", maz[i]); for(int j = 0; j < W; j++) if(maz[i][j] == 'S') sx = i, sy = j; else if(maz[i][j] == 'E') ex = i, ey = j; } if(bfs()) puts("Yes"); else puts("No"); } return 0; }