2013-07-31 22:48:07Morris

[UVA][bfs] 928 - Eternal Truths

Problem I

Eternal Truths

 

History is filled with legends and stories associated with mazes and labyrinths that have been shrouded by mystery. 

In some ancient religion a maze functioned as a cult center and symbolized mankind's search for all eternal truths.

In their initiation cult young people have to pass across a maze composed by squared chambers that can communicate with the ones at the north, south, east or west. They have to go from a start point to an end point passing by the shortest number of chambers and have to follow some ritual. They have to respect a sequence of 3 moves that will be repeated until the end point is reached. In the first move they pass through one chamber, in the second through two chambers and in the third through three chambers. In each of these moves they can�t change their direction.

Problem

Given a map of the chambers disposed in a rectangular grid find the shortest path, in number of moves, from a start point to an end point.

Notice that, in the sequence of moves the ritual described above must be respected. In each move you must pass through the corresponding number of chambers, without changing your direction during a move. You must begin with 1 chamber and repeat the sequence of 1, 2 and 3 chambers until the end is reached. The end can be reached in any of the states.


Input

The first line contains the number of test cases.

The first line of each test case contains two integers separated by a single space: R (2<= R<= 300) corresponding to the number of rows and C (2 <= C <= 300) corresponding to the number of columns.

Each of the following R lines contains C characters. For each character, a dot  "."  represents a chamber, a hash mark "#" represents a wall and the capital letters "S" and "E"  represent the start and the end position respectively.

Output

The output consists of one line for each test case containing the number of moves from "S" to "E" or the word "NO" if there is no solution.

Sample Input

2

5 4

S...

.#.#

.#..

.##.

...E

6 6

.S...E

.#.##.

.#....

.#.##.

.####.

......

Sample Output

NO

3


MIUP2004: Fourth Portuguese National Programming Contest


Problem setter: Ana Paula Maldonado

題目希望找到一次分別走 1, 2, 3, 1, 2, 3, 1, 2 ... 的方式抵達終點。

問最少步數為何。

由於步數是循環的,因此多記錄一個上次走了多少步。



#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
char g[305][305];
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
int x, y, s, tx, ty, ts;
int main() {
    int testcase;
    int n, m;
    int i, j;
    scanf("%d", &testcase);
    while(testcase--) {
        scanf("%d %d", &n, &m);
        for(i = 0; i < n; i++)
            scanf("%s", &g[i]);
        int sx, sy, ex, ey;
        for(i = 0; i < n; i++) {
            for(j = 0; j < m; j++) {
                if(g[i][j] == 'S')
                    sx = i, sy = j;
                if(g[i][j] == 'E')
                    ex = i, ey = j;
            }
        }
        int dp[305][305][3] = {};//1,2,3
        queue<int> X, Y, S;
        for(i = 0; i < 4; i++) {
            tx = sx+dx[i], ty = sy+dy[i];
            if(tx < 0 || ty < 0 || tx >= n || ty >= m)
                continue;
            if(g[tx][ty] == '#')    continue;
            dp[tx][ty][0] = 1;
            X.push(tx), Y.push(ty), S.push(0);
        }
        while(!X.empty()) {
            x = X.front(), X.pop();
            y = Y.front(), Y.pop();
            s = S.front(), S.pop();
            if(s == 0)  ts = 1;//step2
            if(s == 1)  ts = 2;//step3
            if(s == 2)  ts = 0;//step1
            for(i = 0; i < 4; i++) {
                int err = 0;
                tx = x, ty = y;
                for(j = 0; j <= ts; j++) {
                    tx += dx[i], ty += dy[i];
                    if(tx < 0 || ty < 0 || tx >= n || ty >= m) {
                        err = 1;
                        continue;
                    }
                    if(g[tx][ty] == '#')
                        err = 1;
                }
                if(err == 0) {
                    if(dp[tx][ty][ts] == 0) {
                        X.push(tx), Y.push(ty), S.push(ts);
                        dp[tx][ty][ts] = dp[x][y][s]+1;
                    }
                }
            }

        }
        int ret = 0xffff;
        for(i = 0; i < 3; i++)
            if(dp[ex][ey][i])
                ret = min(ret, dp[ex][ey][i]);
        if(ret != 0xffff)
            printf("%d\n", ret);
        else
            puts("NO");
    }
    return 0;
}