뭉지(moonz)
작은 발자국들의 위대한 여정
뭉지(moonz)
  • All (202)
    • Test Code (4)
    • 백엔드 개발하며 작성한 (27)
      • Spring (17)
      • 데이터베이스 (7)
      • 기억할 내용 (3)
    • 언어 (53)
      • Java (25)
      • node.js (7)
      • Python (21)
    • 클라우드 (6)
    • Algorithm & Data Structure (51)
      • 개념 (15)
      • 문제 풀이 (36)
    • 유용한 모든 것 (16)
    • monologue (7)
      • 업무 노트 (1)
      • 관리 로그 (0)
      • 내 이야기 공책 (6)
    • Project (2)
    • TroubleShooting (8)
    • 지식 (18)
      • Machine Learning (6)
      • Review (7)
      • Web (5)
    • Computer Science (5)

블로그 메뉴

  • 홈
  • 태그

인기 글

최근 글

최근 댓글

전체 방문자
오늘
어제

티스토리

hELLO · Designed By 정상우.
뭉지(moonz)

작은 발자국들의 위대한 여정

Algorithm & Data Structure/문제 풀이

[JAVA] baekjoon 1891 사분면

2022. 6. 13. 14:45
반응형

문제

https://www.acmicpc.net/problem/1891

 

1891번: 사분면

첫 줄에 이동시키려는 사분면 조각 번호의 자릿수를 나타내는 정수 d와, 그 사분면 조각의 번호가 주어진다. (1 ≤ d ≤ 50) 둘째 줄에는 이동의 내용을 나타내는 두 정수가 x, y가 주어진다. (|x|, |y|

www.acmicpc.net

 

나의 풀이

1. 주어진 사분면 정보를 기반으로 위치 (row, column) 찾는다.

2. 찾은 위치를 이동시키고 범위를 확인한다.

  - 범위가 벗어나면 -1을 출력하고 종료한다.

3. 이동한 위치의 사분면을 찾는다.

 

 

코드 뜯어보기

초기화 및 입력을 받는 코드입니다.

저는 변수 d를 이용해서 한 변의 길이를 의미하는 size 변수를 미리 할당해놓았습니다.

d는 최대 50까지 들어올 수 있기 때문에 size도 long 타입으로 선언합니다.

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer st = new StringTokenizer(br.readLine());
    int d = Integer.parseInt(st.nextToken());
    String quadrantInfo = st.nextToken();
    long size = (long)Math.pow(2, d);

    st = new StringTokenizer(br.readLine());
    long moveCol = Long.parseLong(st.nextToken());
    long moveRow = Long.parseLong(st.nextToken());

 

String타입인 사분면으로 위치를 찾는 메서드입니다.

각 사분면에 따라 크기를 더해나갔고, 점점 사분면이 분할될 수록 size도 절반으로 줄도록 했습니다. 

반복문은 크기만큼 돕니다. (변수 d와 같은 값)

private static void findLocation(String quadrantInfo, long size) {
    for (int i=0; i<quadrantInfo.length(); i++) {
        size/=2;
        int quardrant =quadrantInfo.charAt(i) - '0';
        switch (quardrant) {    // 2사분면은 그대로
            case 1 : colLoc += size; break;
            case 3 : rowLoc += size; break;
            case 4 :
                rowLoc += size;
                colLoc += size;
        }
    }
}

 

위치를 찾았다면 해당 위치를 이동시킨 후 범위에 있는지 확인하는 코드입니다.

이동시킬 때 row는 위아래로 이동시키는데 문제에서 위로 이동시킬 때 양수라고 했으므로 row에 대해서만 마이너스로 진행하면 됩니다.

만약 이동할 수 있다면 findQuadrant 메서드를 호출합니다.

// main 메서드
        //2. 위치 이동
        rowLoc -= moveRow;   // +1이 위로 이동=> 좌표 상은 -
        colLoc += moveCol;
        // 3. 이동한 위치의 사분면 찾기
        if (outOfBoundary(rowLoc, colLoc, size)) System.out.println("-1");
        else
            findQuadrant(rowLoc, colLoc, size);
	//생략
    }
    
// main메서드 외부
    private static boolean outOfBoundary(long row, long col, long size) {
            return (row<0 || row>= size || col<0 || col>= size);
    }

 

이동한 최종 위치에 대해서 정답을 찾기 위해 분할을 반복하는 메서드입니다. (재귀 이용)

그리고 어떤 사분면이냐에 따라 위치를 size만큼 -(마이너스) 하는데 

해당 문제에서는 2사분이 왼쪽&위에 위치해서 위치를 이동시킬 필요가 없는 위치입니다.

 

매 재귀에서 어떤 사분면에 속하는지 StringBuilder에 추가해주었습니다.

size가 계속해서 반씩 줄다가 길이가 1이 됐을 때 종료합니다. 

// 위치에 따른 사분면 String을 찾는다.
private static void findQuadrant(long row, long col, long size) {
    if (size == 1) {
        System.out.println(answerSB);
        return;
    }
    if (row < size / 2 && col >= size / 2) {//1
        answerSB.append(1);
        findQuadrant(row, col - size / 2, size / 2);
    }
    if (row < size / 2 && col < size / 2) {//2
        answerSB.append(2);
        findQuadrant(row, col, size / 2);
    }
    if (row >= size / 2 && col < size / 2) {//3
        answerSB.append(3);
        findQuadrant(row - size / 2, col, size / 2);
    }
    if (row >= size/2 && col >= size/2) {//4
        answerSB.append(4);
        findQuadrant(row - size / 2, col - size / 2, size / 2);
    }
}

 

 

NumberFormatException 에러

혹시 계속 NumberFormatException 에러가 발생한다면 아래 반례를 실행해봅시다.

50 12341234123412341234123412341234123412341234123412
500000 3000000000

반례 출처

 

원인은?

더보기

문제에서 두번째 줄에 입력받는 이동 x, y는 2의 50승까지 들어올 수 있습니다.

그렇기 때문에 int 타입으로는 (위 반례와 같이) 크기가 큰 수가 들어왔을 때 잘못된 답이 나옵니다.

 

필자는 위 에러를 해결하기 위해 (타입이 문제라는 생각을 못해서..) 괜한 곳을 많~이 수정했습니다.

그래서 아래 코드는 초기 코드에서 많이 수정된 코드입니다.

  • 인자로 StringBuilder를 넘겨주던 코드  => static으로 선언
    • 그래서 초기에는 StringBuilder에 값을 추가해주는 것과 동시에 넘겨주도록 했습니다.
      findQuadrant(row - size / 2, col - size / 2, size / 2, answerSB.append(4));
  • 인자로 row, col을 갖고있는 배열을 넘겨주는 것 => 배열이 아닌 각각의 변수로 넘겨줌

 

나의 전체 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class boj_1891_13 {
    static long rowLoc = 0;
    static long colLoc = 0;
    static StringBuilder answerSB = new StringBuilder();
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int d = Integer.parseInt(st.nextToken());
        String quadrantInfo = st.nextToken();
        long size = (long)Math.pow(2, d);

        st = new StringTokenizer(br.readLine());
        long moveCol = Long.parseLong(st.nextToken());
        long moveRow = Long.parseLong(st.nextToken());

        //1. 사분면에 따라 위치 찾기
        findLocation(quadrantInfo, size);
        //2. 위치 이동
        rowLoc -= moveRow;   // +1이 위로 이동=> 좌표 상은 -
        colLoc += moveCol;
        // 3. 이동한 위치의 사분면 찾기
        if (outOfBoundary(rowLoc, colLoc, size)) System.out.println("-1");
        else
            findQuadrant(rowLoc, colLoc, size);
    }

    // 위치에 따른 사분면 String을 찾는다.
    private static void findQuadrant(long row, long col, long size) {
        if (size == 1) {
            System.out.println(answerSB);
            return;
        }
        if (row < size / 2 && col >= size / 2) {//1
            answerSB.append(1);
            findQuadrant(row, col - size / 2, size / 2);
        }
        if (row < size / 2 && col < size / 2) {//2
            answerSB.append(2);
            findQuadrant(row, col, size / 2);
        }
        if (row >= size / 2 && col < size / 2) {//3
            answerSB.append(3);
            findQuadrant(row - size / 2, col, size / 2);
        }
        if (row >= size/2 && col >= size/2) {//4
            answerSB.append(4);
            findQuadrant(row - size / 2, col - size / 2, size / 2);
        }
    }

    private static boolean outOfBoundary(long row, long col, long size) {
        return (row<0 || row>= size || col<0 || col>= size);
    }

    private static void findLocation(String quadrantInfo, long size) {
        for (int i=0; i<quadrantInfo.length(); i++) {
            size/=2;
            int quardrant =quadrantInfo.charAt(i) - '0';
            switch (quardrant) {    // 2사분면은 그대로
                case 1 : colLoc += size; break;
                case 3 : rowLoc += size; break;
                case 4 :
                    rowLoc += size;
                    colLoc += size;
            }
        }
    }
}
반응형
저작자표시 (새창열림)

'Algorithm & Data Structure > 문제 풀이' 카테고리의 다른 글

[HackerRank] SQL 문제  (0) 2022.06.26
[JAVA] baekjoon 2447 별 찍기-10  (0) 2022.06.15
[JAVA, 백준] 16947. 서울 지하철 2호선  (0) 2022.04.18
[Concept/Algorithm] 이분/이진 탐색 (Binary Search)  (0) 2022.04.17
[JAVA] 프로그래머스 - 행렬 테두리 회전하기 LV2  (0) 2022.04.01
    'Algorithm & Data Structure/문제 풀이' 카테고리의 다른 글
    • [HackerRank] SQL 문제
    • [JAVA] baekjoon 2447 별 찍기-10
    • [JAVA, 백준] 16947. 서울 지하철 2호선
    • [Concept/Algorithm] 이분/이진 탐색 (Binary Search)
    뭉지(moonz)
    뭉지(moonz)
    제가 깨달은 것을 정리하는 공간입니다. 🧡

    티스토리툴바