경험의 기록

문제 : https://www.acmicpc.net/problem/1913

 

1913번: 달팽이

N개의 줄에 걸쳐 표를 출력한다. 각 줄에 N개의 자연수를 한 칸씩 띄어서 출력하면 되며, 자릿수를 맞출 필요가 없다. N+1번째 줄에는 입력받은 자연수의 좌표를 나타내는 두 정수를 한 칸 띄어서

www.acmicpc.net

 

 

풀이

// [백준] 1913. 달팽이 (Java)
import java.io.BufferedReader;
import java.io.InputStreamReader;
 
public class Main {
	static int[][] arr;
	static int n;
	static int x;
	// 상우하좌
	static int[] dx = {-1,0,1,0};
	static int[] dy = {0,1,0,-1};
	
  
    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(br.readLine());
        x = Integer.parseInt(br.readLine());
        int resultRow = 0;
        int resultCol = 0;
        arr = new int[n][n];
        
        // 시간초과 방지
        StringBuilder sb = new StringBuilder();

        create();
 
        for(int i = 0 ; i < n; i++) {
        	for(int j = 0; j < n; j++) {
        		sb.append(arr[i][j] + " ");
        		// 입력받은 자연수 좌표 저장
        		if(arr[i][j] == x) {
        			resultRow = i + 1;
        			resultCol = j + 1;
        		}
        	}
        	sb.append("\n");
        }
        
        sb.append(resultRow + " " + resultCol);
        System.out.println(sb);
        
        br.close();
    }
    
    
    // 표 생성
    public static void create() {
    	int curRow = n / 2;
    	int curCol = n / 2;
    	
    	int next = 0;
    	int count = 0; // 같은 방향 이동 횟수
    	
    	int max = 1; // 최대 이동 횟수
    	int ls =0; // 방향 전환 횟수
    	
    	// n^2 만큼 반복
    	for(int i = 1; i <= n * n; i++) {
    		arr[curRow][curCol] = i;
    		
    		// 현재 방향으로 위치 한칸 이동
    		curRow += dx[next % 4];
    		curCol += dy[next % 4];
    		count++;
    			
    		// 방향전환 (최대 이동횟수만큼 그 방향으로 이동했다면)
    		if(count == max) {
    			next++;
    			count = 0;
    			ls++;
    		}
    		
    		// 방향전환 2번 될 때마다 최대 이동횟수 ++
    		if(ls == 2) {
    			max++;
    			ls = 0;
    		}
    	}
    }
}

달팽이 모양의 패턴을 살펴보면

안쪽부터 위로 1칸, 오른쪽으로 1칸, 밑으로 2칸, 왼쪽으로 2칸, 위로 3칸, 오른쪽으로 3칸... 처럼

상하좌우로 이동하는 것을 알 수 있고

두번 방향을 전환할때마다 이동하는 최대거리가 1씩 증가하는 것을 확인할 수 있다.

 

이를 바탕으로 배열을 구현하면 된다.

 

1. 달팽이 배열 만들기

방향이 상우하좌 순으로 변하므로

델타탐색을 이용하기 위해 상우하좌로 세팅해주고

 

맨 처음에 가운데(n/2 , n/2) 에서 시작하여

현재 방향으로 이동시키고,

최대 이동횟수만큼 이동했다면 델타 좌표를 증가시켜 방향을 바꿔준다.

또한 방향이 2번바뀔때마다 최대 이동횟수를 증가시켜준다.

 

2. 출력하기

N의 범위가 최대 999이므로

999 * 999 행렬을 출력하려면 많은 시간이 소모되므로

StringBuilder의 append를 사용하여

배열 원소값을 전부 합친 후

 

한번에 출력해준다.

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading