반응형
12-24 07:02
Today
Total
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
관리 메뉴

개발하는 고라니

[백준] 1726번 : 로봇 본문

Programming/백준

[백준] 1726번 : 로봇

조용한고라니 2021. 2. 19. 14:05
반응형
 

1726번: 로봇

많은 공장에서 로봇이 이용되고 있다. 우리 월드 공장의 로봇은 바라보는 방향으로 궤도를 따라 움직이며, 움직이는 방향은 동, 서, 남, 북 가운데 하나이다. 로봇의 이동을 제어하는 명령어는

www.acmicpc.net


[우선순위 큐 + BFS]

우선순위 큐를 사용한 이유에 대해서는 이따 반례와 함께 언급하고, 큐에 들어가야 하는 원소는 4가지 이다. 위치의 좌표(y, x), direction, 명령을 실행한 횟수(cnt)이다. 방향은 4가지 (동:1, 서:2, 남:3, 북:4)이고, 각 칸으로 최대 3칸 까지 갈 수 있으므로,

int[][] X =

{{1, 2, 3},

{-1, -2, -3},

{0, 0, 0},

{0, 0, 0}}

 

int[][] Y =

{{0, 0, 0},

{0, 0, 0},

{1, 2, 3},

{-1, -2, -3}};

의 2차원 배열을 초기화한다. 이는 각 동, 서, 남, 북을 가르키고, 1, 2, 3칸을 갈 수 있는 배열이다. 단, 현재 좌표에서 1칸이든 2칸이든 앞에 '1'(벽)이 있다면 그 이후의 칸에 대해서는 갈 수 없음을 유의한다.

 

그리고 회전하는 것에 대해 명령 실행 횟수를 추가하는 것은

동 -> 서 혹은 서 -> 동 및 북 -> 남 혹은 남 -> 북 일 때를 제외하고는, 1칸 씩 추가하게 된다.

2칸씩 추가하게 되는 것. 즉 동->서, 남->북을 숫자로 정의하였다.

 

동:1 서:2 이므로, 서로 다른 임의의 방향 2개를 더해 3이 된다면, 각각 동, 서 임이 분명하므로 명령 실행 횟수를 2 추가한다.

남:3 북:4 이므로, 서로 다른 임의의 방향 2개를 더해 7이 된다면, 각각 북, 남 임이 분명하므로 명령 실행 횟수를 2 추가한다.

 

우선순위 큐를 쓴 이유:

5 6
1 1 1 1 1 1
1 0 0 0 0 1
1 0 1 1 0 1
1 0 0 0 0 1
1 1 1 1 1 1
2 2 3
4 5 1


답:3 오답:4

Red에서 Blue로 가야하는데, 시작 방향이 남쪽을 향해있고, 도착 방향은 동쪽을 향해있다. 따라서 3번만에 갈 수 있는데, 일반 큐를 쓰면 들어가는 순서에 따라 원소가 나오게 되어, 항상 최적해를 찾진 못한다. 따라서 우선순위 큐를 사용함으로써 더 적은 비용으로 도착 정점에 도달하는 것을 추구하도록 한다.

# Code </>

public class Main {

    static class Point implements Comparable<Point>{
        int y, x, dir, cnt;

        public Point(int yy, int xx, int dir, int cnt){
            y=yy; x=xx;
            this.dir=dir;
            this.cnt=cnt;
        }
        @Override
        public int compareTo(Point o) {
            return cnt - o.cnt;
        }        
    }

    static int n, m;
    static int[][] map = new int[101][101], dp = new int[101][101];
    static boolean[][] visit = new boolean[101][101];
    static int[][] X = {{1, 2, 3}, {-1, -2, -3}, {0, 0, 0}, {0, 0, 0}}, Y = {{0, 0, 0}, {0, 0, 0}, {1, 2, 3}, {-1, -2, -3}};

    static int BFS(Point start, Point end){

        Queue<Point> Q = new PriorityQueue<>();

        visit[start.y][start.x] = true;
        dp[start.y][start.x] = 0;
        Q.add(new Point(start.y, start.x, start.dir, 0));

        while(!Q.isEmpty()){
            Point p = Q.poll();

            if(p.y == end.y && p.x == end.x) {

                if(p.dir == end.dir);
                else if(p.dir + end.dir == 3 || p.dir + end.dir == 7) p.cnt += 2;
                else p.cnt +=1;

                return p.cnt;
            }

            int y = p.y;
            int x = p.x;
            int dir = p.dir;
            int cnt = p.cnt;

            for(int a=1; a<=4; a++) {
                for (int b = 0; b < 3; b++) {
                    int ny = y + Y[a - 1][b];
                    int nx = x + X[a - 1][b];
                    int nCnt = cnt + 1;

                    if (ny < 1 || nx < 1 || ny > n || nx > m || visit[ny][nx]) continue;
                    if(map[ny][nx] == 1) break;

                    if (a == dir) nCnt += 0;
                    else if ((a + dir) == 3 || (a + dir) == 7) nCnt += 2;
                    else nCnt += 1;

                    visit[ny][nx] = true;
                    dp[ny][nx] = nCnt;
                    Q.add(new Point(ny, nx, a, nCnt));
                }
            }
        }
        return -1;
    }

    public static void main(String[] args) 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());

        for(int i=1; i<=n; i++){
            st = new StringTokenizer(br.readLine());
            for(int j=1; j<=m; j++)
                map[i][j] = Integer.parseInt(st.nextToken());
        }

        Point[] points = new Point[2];
        for(int i=0; i<2; i++){
            st = new StringTokenizer(br.readLine());
            int Y = Integer.parseInt(st.nextToken());
            int X = Integer.parseInt(st.nextToken());
            int Dir = Integer.parseInt(st.nextToken());
            points[i] = new Point(Y, X, Dir, 0);
        }

        System.out.println(BFS(points[0], points[1]));
    }
}
반응형

'Programming > 백준' 카테고리의 다른 글

[백준] 1194번 : 달이 차오른다, 가자  (0) 2021.02.21
[백준] 4179번 : 불!  (0) 2021.02.19
[백준] 5567번 : 결혼식  (0) 2021.02.17
[백준] 5427번 : 불  (0) 2021.02.17
[백준] 13913번 : 숨바꼭질 4  (0) 2021.02.17
Comments