3009:Curling 2.0

keyword

探索 C++

概要

2次元のボード上に石がいくつかある。この上でカーリングをして滑るヤツを目的地に持っていきたい。滑るヤツは石に当たるまで止まらないし、石に当たるとぶつかった石を破壊する。最短で何回滑らせれば良いか求める問題。ただし10回以上滑らせてはいけない。
実装ゲー。最大計算量もたかが知れているので愚直に探索すればよい。

char board[22][22];
int sx, sy, gx, gy;
int n, m;
int dx[] = {0,0,1,-1}, dy[] = {1,-1,0,0};

inline int dfs(int y, int x, int depth){
    if(depth >= 10) return 1<<10;
    int k, nx, ny, ans = 1<<10;
    REP(k,4){
        ny = y + dy[k];
        nx = x + dx[k];
        if(board[ny][nx] == 1) continue;
        while(!board[ny][nx]){
            ny += dy[k];
            nx += dx[k];
        }
        if(board[ny][nx] == 3) return depth+1;
        if(board[ny][nx] == 1){
            board[ny][nx] = 0;
            ans = min(ans, dfs(ny-dy[k],nx-dx[k],depth+1));
            board[ny][nx] = 1;
        }
    }
    return ans;
}

int main(){
    int i, j;
    while(m = readint(), n = readint(), n){
        REP(i,n+2)REP(j,m+2) board[i][j] = 4;
        FOR(i,1,n+1)FOR(j,1,m+1){
            board[i][j] = readint();
            if(board[i][j] == 2){
                sy = i, sx = j;
                board[i][j] = 0;
            }
            if(board[i][j] == 3){
                gy = i, gx = j;
            }
        }
        int ans = dfs(sy,sx,0);
        printf("%d\n",ans<=10?ans:-1);
    }

    return 0;
}