Problem : https://www.acmicpc.net/problem/1891
1891번: 사분면
첫 줄에 이동시키려는 사분면 조각 번호의 자릿수를 나타내는 정수 d와, 그 사분면 조각의 번호가 주어진다. (1≤d≤50) 둘째 줄에는 이동의 내용을 나타내는 두 정수가 x, y가 주어진다. (|x|, |y|≤2
www.acmicpc.net
Approach
분할 정복(Divide & Conquer)
을 구현한 문제이다.
아래와 같이 두 가지 기능을 구현하여야 한다. 그리고 순서대로 수행하면서 답을 도출한다.
- 주어진 사분면 숫자의 위치 (x, y)를 찾는다. 그리고 그 위치에 주어진 이동 횟수를 더한 위치를 찾는다.
- 구한 위치의 사분면 숫자를 구한다.
1번 기능
의 경우, 주어진 사분면 숫자를 앞에서부터 한 자리씩 읽으면서 대략의 위치를 가늠한다. (사분면 숫자를 보고 (a, b) ~ (a', b') 범위를 찾는다.)
주어진 좌표평면의 한 변의 길이는 (1 << d) 인 정사각형이다. 그러므로 findLoc() 메소드를 d번 호출하면 된다.
2번 기능
의 경우, 좌표를 기준으로 한 변의 길이가 (1 << d)인 정사각형에서의 대략의 위치를 가늠한다. (몇 사분면인지)
d의 숫자를 하나씩 줄이며(한변의 길이를 계속 반으로 줄이면서) 0이 될 때까지 반복한다. (이 때 한 변의 길이는 1이 된다.)
사분면 숫자와 좌표를 구하는 자세한 구현 방법은 아래 코드를 참조하면 좋을 것이다.
Code
import java.io.*;
import java.util.StringTokenizer;
/**
* No.1891: 사분면
* Hint: Divide & Conquer + 구현
*/
public class BOJ1891 {
static int d;
static long tx, ty;
static int[] arr;
static StringBuilder sb = new StringBuilder();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
d = Integer.parseInt(st.nextToken());
arr = new int[d];
String num = st.nextToken();
for (int i = 0; i < d; i++) {
arr[i] = num.charAt(i) - '0';
}
st = new StringTokenizer(br.readLine());
long moveH = Long.parseLong(st.nextToken()); // 가로 이동
long moveV = Long.parseLong(st.nextToken()); // 세로 이동
long n = 1L << d;
findLoc(0,0,0, n, n);
tx -= moveV;
ty += moveH;
if (tx >= 0 && tx < n && ty >= 0 && ty < n) {
findNum(d, tx, ty);
} else {
bw.write("-1");
}
bw.write(sb.toString());
bw.close();
br.close();
}
// 주어진 위치로 사분면 찾기
static void findNum(int depth, long tx, long ty) {
if (depth == 0) {
return;
}
long half = 1L << (depth - 1);
if (tx < half && ty >= half) {
sb.append("1");
findNum(depth - 1, tx, ty - half);
} else if (tx < half && ty < half) {
sb.append("2");
findNum(depth - 1, tx, ty);
} else if (tx >= half && ty < half) {
sb.append("3");
findNum(depth - 1, tx - half, ty);
} else if (tx >= half && ty >= half) {
sb.append("4");
findNum(depth - 1, tx - half, ty - half);
}
}
// 주어진 사분면 숫자의 위치 찾기
static void findLoc(int numIdx, long lx, long ly, long rx, long ry) {
if (numIdx == d) {
tx = lx;
ty = ly;
return;
}
int num = arr[numIdx];
if (num == 1) { // 1사분면
findLoc(numIdx + 1, lx, (ly + ry) / 2, (lx + rx) / 2, ry);
} else if (num == 2) { // 2사분면
findLoc(numIdx + 1, lx, ly, (lx + rx) / 2, (ly + ry) / 2);
} else if (num == 3) { // 3사분면
findLoc(numIdx + 1, (lx + rx) / 2, ly, rx, (ly + ry) / 2);
} else if (num == 4) { // 4사분면
findLoc(numIdx + 1, (lx + rx) / 2, (ly + ry) / 2, rx, ry);
}
}
}
'Algorithm > Baekjoon Online Judge' 카테고리의 다른 글
[Java] 백준 21774 (가희와 로그 파일) Gold 3 (0) | 2021.06.02 |
---|---|
[Java] 백준 21773 (가희와 프로세스 1) Gold 5 (0) | 2021.06.02 |
[Java] 백준 1201 (NMK) Platinum 3 (0) | 2021.06.01 |
[Java] 백준 2873 (롤러코스터) Platinum 3 (0) | 2021.05.25 |
[Java] 백준 12904 (A와 B) Gold 5 (0) | 2021.05.23 |