백준 1022번 소용돌이 예쁘게 출력하기

이상민·2023년 11월 15일
0

알고리즘

목록 보기
96/128
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class TornadoPrint {
    static int[] dr = {0,-1,0,1};
    static int[] dc = {1,0,-1,0};
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        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[][] map = new int[50][5];
        int row = 10001/2;
        int col = 10001/2;
        int count = 2;
        int dir = 0;
        if(r1<=0&&r2>=0&&c1<=0&&c2>=0){
            map[row-(10001/2+r1)][col-(10001/2+c1)] = 1;
        }
        int dircnt = 1;
        int cnt = 1;
        while (true){
            if(count==100020002) break;

            for (int i = 0; i < cnt; i++) {
                if(count==100020002) break;
                row += dr[dir%4];
                col += dc[dir%4];
                if(row>=10001/2+r1&&row<=10001/2+r2&&col>=10001/2+c1&&col<=10001/2+c2){
                    map[row-(10001/2+r1)][col-(10001/2+c1)] = count;

                }
                count++;
            }
            if(dircnt%2==0) cnt++;
            dir++;
            dircnt++;
        }
        int max = 0;
        for (int i = 0; i <= r2-r1; i++) {
            for (int j = 0; j <= c2-c1; j++) {
                StringBuilder sb = new StringBuilder();
                sb.append(map[i][j]);
                max = Math.max(sb.length(),max);
            }
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i <= r2-r1; i++) {
            for (int j = 0; j <= c2-c1; j++) {
                StringBuilder sb = new StringBuilder();
                sb.append(map[i][j]);
                for (int k = 0; k < max-sb.length(); k++) {
                    stringBuilder.append(" ");
                }
                stringBuilder.append(map[i][j]).append(" ");
            }
            if(i==r2-r1)break;
            stringBuilder.append("\n");
        }
        System.out.println(stringBuilder);
    }
}

문제 조건

  1. -5 000 ≤ r1, c1, r2, c2 ≤ 5,000
    0 ≤ r2 - r1 ≤ 49
    0 ≤ c2 - c1 ≤ 4

  2. 만약 수의 길이가 가장 길이가 긴 수보다 작다면, 왼쪽에서부터 공백을 삽입해 길이를 맞춘다.

풀이방법

📢해당풀이의 전체적인 접근은, 입력값의 최대범위에 맞게 배열을 생성한다고 가정하고, 안에 소용돌이 형태로 수를 넣는것이다.
단, 이때 실제로 최대범위로 배열을 생성해버리면 메모리초과가 발생하므로, 출력하는 범위에 맞게 배열을 생성하고, 출력범위에 해당할 때에만 수를 넣는다.

  1. 소용돌이는 한방향에 cnt만큼 count값을 하나씩 증가시키며 넣는다.
    예를들어,1을 초깃값으로 넣고,
    cnt = 1일때, 2 넣고 방향전환, 3 넣고 방향전환,
    두번 방향전환 했다면 cnt값 증가
    cnt = 2일때, 4넣고 5넣고, 방향전환, 6넣고 7넣고 방향전환,
    두번 방향전환 했다면 cnt값 증가
    ...
  2. 단, 이때 출력범위에 해당할때만, 실제로 값을 넣어줘야 하므로, 범위를 지정하고, 범위에 해당할때만, 출력map에 count값을 넣어준다.
  3. count값이 최대인 5001x5001 = 100020001가 되면, 반복문을 탈출한다
  4. 출력맵을 돌며 해당 자릿수의 최댓값을 구한다.
  5. stringBuilder를 통해 출력값을 만드는데, 현재 숫자가 4번에서 구한 최댓값보다 작다면, 작은만큼 공백을 반복해서 넣어준다.
    마지막 줄은 줄바꿈을 하지 않는다.
  6. 이후 stringBuilder를 출력해준다.

후기

소용돌이 형태의 map을 만드는 방법은 여러가지가 있는데, 여러가지의 방법을 알고 있었어서 조건에 맞는 방법을 골라 쓸 수 있었다고 생각한다.
처음에 생각한 방법으로는 가상의 배열이라는 조건에 맞출수 없어서,
해당 조건에 맞게 규칙을 찾아 다시 설계하였다.
행과 열이 기본형태로 나오는게 아니라 중앙에서부터 0,0이어서 범위를 조건에 맞게 설정하는것이 까다로운 문제였다.

profile
개린이

0개의 댓글