103. 미친 로봇 (백준 1405) [JAVA]
반응형

문제

문제 링크 : https://www.acmicpc.net/problem/1405

 

1405번: 미친 로봇

첫째 줄에 N, 동쪽으로 이동할 확률, 서쪽으로 이동할 확률, 남쪽으로 이동할 확률, 북쪽으로 이동할 확률이 주어진다. N은 14보다 작거나 같은 자연수이고,  모든 확률은 100보다 작거나 같은 자

www.acmicpc.net

문제

통제 할 수 없는 미친 로봇이 평면위에 있다. 그리고 이 로봇은 N번의 행동을 취할 것이다.

각 행동에서 로봇은 4개의 방향 중에 하나를 임의로 선택한다. 그리고 그 방향으로 한 칸 이동한다.

로봇이 같은 곳을 한 번보다 많이 이동하지 않을 때, 로봇의 이동 경로가 단순하다고 한다. (로봇이 시작하는 위치가 처음 방문한 곳이다.) 로봇의 이동 경로가 단순할 확률을 구하는 프로그램을 작성하시오. 예를 들어, EENE와 ENW는 단순하지만, ENWS와 WWWWSNE는 단순하지 않다. (E는 동, W는 서, N은 북, S는 남)

입력

첫째 줄에 N, 동쪽으로 이동할 확률, 서쪽으로 이동할 확률, 남쪽으로 이동할 확률, 북쪽으로 이동할 확률이 주어진다. N은 14보다 작거나 같은 자연수이고, 모든 확률은 100보다 작거나 같은 자연수 또는 0이다. 그리고, 동서남북으로 이동할 확률을 모두 더하면 100이다.

확률의 단위는 %이다.

출력

첫째 줄에 로봇의 이동 경로가 단순할 확률을 출력한다. 절대/상대 오차는 10-9 까지 허용한다.

풀이

풀이 자체는 간단하다.

N만큼 동서남북으로 움직일 때, 이동 경로가 단순한지 확인하면 된다.

이동 경로가 단순한지의 여부를 확인하기 위해 지도를 만들어준다.

우선 최대 14만큼 동,서,남,북으로 움직일 수 있기 때문에 29X29의 크기면 충분하다. (가운데인 14,14에서 시작한다.)

각각의 방향으로 움직일 때 마다 방문 여부를 체크하는 방식으로 이동 경로가 단순한지 확인할 수 있다.

재귀를 통해 한칸씩 이동하면서 확인하면 되고, 전체 확률은 각 움직임에서의 확률의 곱을 해주면 된다.

이때 풀이를 하며 실수하기 쉬운 점은, X,Y좌표의 이동 순서와 입력받은 동,서,남,북의 순서가 일치해야 하는 부분이다.

코드

import java.io.*;
import java.util.*;

public class Main {

    static int N;
    //E W S N
    static double[] percent = new double[4];

    //시작점은 14,14
    static boolean[][] visited = new boolean[29][29];
    static int[] moveX = {1,-1,0,0};
    static int[] moveY = {0,0,1,-1};

    static double answer = 0;

    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());

        for(int i=0; i<4; i++){
            percent[i] = Double.parseDouble(st.nextToken())/100;
        }

        path(0,14,14,1);

        System.out.println(answer);

    }

    public static void path(int count, int x, int y, double currentPer){

        if(count == N){
            answer += currentPer;
            return;
        }

        visited[y][x] = true;
        int curX, curY;
        for(int i=0; i<4; i++){
            curX = x+moveX[i];
            curY = y+moveY[i];
            if(!visited[curY][curX]){
                path(count+1, curX, curY, currentPer*percent[i]);
            }
        }
        visited[y][x] = false;

    }
}

결과

반응형