🧫 문제 분석
✔️ 출처
📖 문제

좌표 (0,0) 에서 시작해서
상하좌우로 이동한다.
이동 방향은
→ ↑ ← ↓ 이렇게 반시계방향이며
이동 거리는 1에서 시작해서
2번 방향을 전환하면 이동거리는 1씩 증가

이동 한 좌표를 갱신하면서
현재 위치가 문제에서 주어진 r2,r1,c1,c2 박스 범위 안에 있는지 확인한다.
범위 안에 있다면 그 위치에 숫자를 넣어주면 된다. (숫자는 이동할때마다 1씩 증가)
문제는 r1,c1,r2,c2가 -5000 ~ 5000까지 범위인데
우리가 만드는 배열들은 음수 인덱스 표현이 안된다.
이렇게 시작지점을 0,0으로 끌어당겨야한다.
arr[현재 위치r - r1] [현재 위치c - c1] 로 인덱스에 접근하면
r1, r2가 0,0으로 맞춰져서 배열 안 범위로 들어갈 것이다.

출력
출력은 String.format을 사용하여 %(max숫자길이 + 1)d 로 포맷만들고 출력하였다.
+1을 한 이유는 '각 원소는 공백으로 구분한다. ' 라는 조건때문이며,
최대 길이인 숫자도 한칸 띄우기 위함이다.
그럼 처음 출력된 것도 공백이 생기는데
이는 따로 if문으로 조건 처리하면된다. ( 숫자길이 -1 로 출력하게끔)
🔅 문제 풀이
import java.io.*;
import java.util.*;
public class Main {
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());
int r1 = Integer.parseInt(st.nextToken());
int c1 = Integer.parseInt(st.nextToken());
int r2 = Integer.parseInt(st.nextToken());
int c2 = Integer.parseInt(st.nextToken());
// 소용돌이 순서 오른쪽 - 위 - 왼쪽 - 아래
int[] dx = {1, 0, -1, 0};
int[] dy = {0, -1, 0, 1};
// 소용돌이를 출력할 배열 생성
int[][] map = new int[r2- r1 + 1][c2 - c1 + 1];
// 현 위치
int[] pos = {0, 0};
int fullCheck = 0; // 다 채워졌는지 확인
int n = 1; // 현재 소용돌이 번호
// 0,0 부터 확인
if (checkBoundary(r2, pos, r1, c2, c1)) {
map[pos[0] - r1][pos[1] - c1] = n;
fullCheck++;
}
int moveDistance = 1; // 이동 길이
int maxLengthNum = 1; // 최댓 값
// 배열에 모두 채워질때까지
while (fullCheck < map.length * map[0].length) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < moveDistance; k++) {
pos[0] += dy[j];
pos[1] += dx[j];
n++;
if (checkBoundary(r2, pos, r1, c2, c1)) {
map[pos[0] - r1][pos[1] - c1] = n;
maxLengthNum = Math.max(maxLengthNum, n);
fullCheck++;
}
}
// 2개의 방향당 이동 거리를 1씩 늘림
if (j % 2 == 1) moveDistance++;
}
}
// 제일 긴 수 길이 얻기
int len = String.valueOf(maxLengthNum).length() + 1;
// 출력
for (int[] arr : map) {
for (int i = 0; i < arr.length; i++) {
bw.write(String.format("%" + (i == 0 ? len - 1 : len) + "d",arr[i]));
}
bw.write("\n");
}
bw.flush();
bw.close();
}
//r2 >= 현재 행 >= r1 && c2 >= 현재 열 >= c1
private static boolean checkBoundary(int r2, int[] pos, int r1, int c2, int c1) {
return r2 >= pos[0] && r1 <= pos[0] && c2 >= pos[1] && c1 <= pos[1];
}
}
❗ 오답노트 / 필요한 지식
- 범위 문제는 항상 인덱스 처리가 문제다. 0,0으로 어떻게 맞출지 항상 생각하자.
'baekjoon' 카테고리의 다른 글
백준 9017번 : 크로스 컨트리 [자바] (1) | 2025.03.08 |
---|---|
백준 18870번 : 좌표 압축 [자바] (1) | 2025.03.02 |
백준 2448번 : 별 찍기 - 11 자바 (1) | 2024.09.13 |
백준 12891번 : DNA 비밀번호 자바 (0) | 2024.09.13 |
백준 1094번 : 막대기 자바 (1) | 2024.09.07 |