를 보면, 완전탐색을 이용 해도 되는 문제인 듯 하다.
백트랙킹 + bfs를 하도록 한다.
각 방향으로 기울이기를 할 때, 매 번, 이런것을 확인해야하는가?
기울이기 구현???
반례
7 7
#######
#...BR#
#.#####
#.....#
#####.#
#O....#
#######
// -1
import java.io.*;
import java.util.*;
public class Main {
public static int[][] dirs = new int[][]{{0,1},{0,-1},{1,0},{-1,0}}; //오른쪽 , 왼쪽, 아래로, 위로 기울이기
public static boolean[][][][] visit = new boolean[10][10][10][10];
public static int[] red = new int[2];
public static int[] blue = new int[2];
public static int n,m;
// String으로 받을까?
public static char[][] board;
public static void Setting() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
board = new char[n][m];
visit = new boolean[n][m][n][m];
// board setting
String temp="";
for(int r=0;r<n;r++){
temp = br.readLine();
for(int c=0;c<m;c++){
board[r][c]= temp.charAt(c);
if(temp.charAt(c) =='R') {
board[r][c] ='.';
red[0] = r;
red[1]=c;
}
else if(temp.charAt(c) =='B'){
board[r][c] ='.';
blue[0] = r;
blue[1]=c;
}
}
}
}
// q에 넣을 때 , 모든 조건을 확인하고 넣는다.
public static int bfs(){
int min = 11;
Queue<int[]> q = new LinkedList<>();
q.add(new int[]{red[0],red[1],blue[0],blue[1],0}); //red location, blue location, depth
visit[red[0]][red[1]][blue[0]][blue[1]] = true;
// q에는 red, blue의 위치,depth 를 저장한다.
while(q.isEmpty()==false) {
int[] cur = q.poll(); // cur[0]: ry, cur[1]:rx, cur[2]:by, cur[3]:bx
// depth가 10이상인 순간 반복문을 종료
if(cur[4]>9) break;
boolean loopr=true,loopb=true;
for (int dir = 0; dir < dirs.length; dir++) {
int nry=cur[0],nrx=cur[1],nby=cur[2],nbx=cur[3];
boolean alreadyMoved = false;
boolean fail = false;
boolean redOut = false;
// RED 먼저 움직이다가, BLUE에 의해 BLOCKED되면 BLUE를 움직이기
// 어차피 #을 만나면 멈추기 때문에 loop condition을 true로 해 두자
while(loopr){
nry+= dirs[dir][0];
nrx+= dirs[dir][1];
// 1. block by blue + blue를 아직 움직인적 없는 경우
if(nry == nby && nrx==nbx && alreadyMoved==false) {
// blue를 먼저 움직이기
while (true) {
alreadyMoved = true;
nby += dirs[dir][0];
nbx += dirs[dir][1];
// blue가 구멍에 빠지는 경우 -> 이 direction 으로의 이동이 실패하는 거임
if (board[nby][nbx] == 'O') {
fail = true;
break;
}
// blue가 이동한 곳이 '.'이 아닌 경우 ('O'였으면 이미 위에서 걸려서 break) -> '#'
else if(board[nby][nbx]!='.') {
nby -= dirs[dir][0];
nbx -= dirs[dir][1];
break;
}
}
// blue가 구멍에 빠진 경우 -> 이 direction을 아예 종료
if(fail) break;
}
// Blue를 통해 이 direction을 종료해야한다고 판단 -> 이 direction을 아예 종료
if(fail) break;
// BLue에의해 막혔고, 이미 BLUE에 의해 막혔어서, Blue를 이동시킨 후인경우
if(nry == nby && nrx==nbx && alreadyMoved) {
// 일단 red의 이동을 취소
nry-= dirs[dir][0];
nrx-= dirs[dir][1];
break;
}
// Blue에 막히지 않은 경우
// Red를 움직이다 'O'에 빠진 경우
if(board[nry][nrx]=='O') {
redOut=true;
break;
}
// Red를 움직이다 '#'에 가로막힌 경우 -> red이동을 취소한다
else if(board[nry][nrx]=='#') {
nry-= dirs[dir][0];
nrx-= dirs[dir][1];
break;
}
}
// RED loop 만 돌았는데 이 direction은 종료해야겠다 싶은 경우
if(fail)continue;
// BLUE를 움직인다
while(loopb){
nby += dirs[dir][0];
nbx+= dirs[dir][1];
// RED에 막히는 경우 && red가 구멍을 통해 빠져나간게 아닌 경우
if(nby == nry && nbx == nrx&& !redOut){
nby -= dirs[dir][0];
nbx -= dirs[dir][1];
break;
}
// blue가 'O'에 빠지는 경우
if(board[nby][nbx]=='O'){
fail = true;
break;
}
// blue가 '#'에 막히는 경우
if(board[nby][nbx]!='.'){
nby -= dirs[dir][0];
nbx -= dirs[dir][1];
break;
}
}
// 이 방향으로 기울이기가 실패인 경우 --> fail이라는 것은, 이 direction으로의 기울이기가 아예 실패인 경우임.
if(fail) continue;
// red만 빠진 경우 -> min을 update한다. red가 구멍에 빠진 경우를 q에 넣지 않게 주의
if(redOut){
if(min>cur[4]+1) {
min = cur[4]+1;
}
continue;
}
// 여기서 나온 nry,nrx,nby,nbx가 이미 visit된 적 있는 경우
if(visit[nry][nrx][nby][nbx]) continue;
// 다른 경우는 q에 넣는다.
q.add(new int[]{nry,nrx,nby,nbx,cur[4]+1});
visit[nry][nrx][nby][nbx] = true;
}
}
return min;
}
public static void main(String[] args) throws IOException {
Setting();
int ans = bfs();
//System.out.println(ans);
if(ans > 10) System.out.println(-1);
else System.out.println(ans);
}
}
10 10
##########
#R#...##B#
#.....##.#
#####.##.#
#......#.#
#.######.#
#.#......#
#.#.#.#..#
#...#.O.##
##########
10 10
##########
#R#...##B#
#.....##.#
#####.##.#
#......#.#
#.######.#
#.#.....##
#.#.#.#.##
#...#O..##
##########
10 10
##########
#R#...##B#
#.....##.#
#####.##.#
#......#.#
#.######.#
#.#....###
#.#.##..##
#...#.#O##
##########
3 10
##########
#.R.B..O.#
##########
3 10
##########
#.B.R..O.#
##########
7 7
#######
#...BR#
#.#####
#.....#
#####.#
#O....#
#######
// -1
8 8
########
#.####.#
#...#B##
#.##.R.#
######.#
##.##O.#
###.##.#
########
//7