코딩테스트/SWEA

[SWEA] 1954. 달팽이 숫자 D2 - Java 자바

yujinius 2024. 5. 8. 09:10

문제 링크

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5PobmqAPoDFAUq#

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

풀이 포인트 : 방향 벡터 설정

 

import java.util.Scanner;

class Solution
{
	public static void main(String args[]) throws Exception
	{
		
		Scanner sc = new Scanner(System.in);
		int T;
		T=sc.nextInt();
		
		// 각각의 테스트 케이스에 대해서 진행
		for(int test_case = 1; test_case <= T; test_case++)
		{
			int num = sc.nextInt(); // 달팽이의 크기 입력 받기
			int snail [][]= new int[num][num]; // num x num 사이즈의 배열 0으로 초기화
			
			// 이동 규칙 벡터 
			int index [][] = {{0, 1}, {1, 0}, {0, -1}, {-1,0}}; // 우 > 하 > 좌 > 상
			//int index [][] = { {1, 0},{0, 1},   {-1,0},{0, -1}}; // 하 > 우 > 상 > 좌
			// 필요 변수 초기화
			// 현재 위치 표시용 now x, y
			int nx = 0;
			int ny = 0;
			// 이동 방향 더해주는 용도 // 처음 방향 우측
			int x = index[0][0];
			int y = index[0][1];
			// 방향 변환 확인용
			int change = 0;
			// 배열에 넣어줄 숫자
			int n  = 1;
			
			// 종료 조건: 마지막 칸 도달 시
			while(n <= num*num) {
				// 값 넣어주기
				snail[nx][ny] = n;
				// 값 증가
				n++;
				// 이동 예정 부분 확인용
				int nextX = nx + x;
				int nextY = ny + y;
				if(nextX>=num || nextY>=num || nextX<0 || nextY<0 || snail[nextX][nextY] !=0) {
					// 범위 밖이거나 || 이미 채워져 있는 곳이라면 
					// 방향 전환
					change = (change+1) % 4;
					// 전환된 방향으로의 벡터 넣기
					x = index[change][0];
					y = index[change][1];
				}
				// 이동 해주기
				nx = nx +x;
				ny = ny +y;
				
				
			}
			
			System.out.printf("#%d", test_case);
			System.out.println();
			for(int i = 0; i<num; i++) {
				for(int j =0; j < num; j++) {
					System.out.print(snail[i][j]+" ");
				}
				System.out.println();
			}
		
			
		}
	}
}

 

아래는 방향 벡터를 dx, dy를 나누어 사용하는 방법이다

import java.util.Scanner;

class Solution
{
	public static void main(String args[]) throws Exception
	{
		
		Scanner sc = new Scanner(System.in);
		int T;
		T=sc.nextInt();
		
		for(int test_case = 1; test_case <= T; test_case++)
		{
			// 테스트 케이스마다 정수 N을 입력 받는다
			int num = sc.nextInt();
			int snail[][] = new int[num][num]; // num x num 크기로 배열 0으로 초기화
			
			// 필요 변수 
			int x = 0; // now x 초기는 0,0시작
			int y = 0; // now y 초기는 0, 0 시작
			
			int direction = 0; // 방향전환
			// 방향 지정 우 0, 1 => 하 1, 0=> 좌 0, -1=> 상 -1, 0
			int dx[] = {0, 1, 0, -1};
			int dy[] = {1, 0, -1, 0};
			
			// 값
			int n = 1;
			
			// 다음 이동 확인 변수
			int nextX = 0;
			int nextY = 0;
			
			
			while(n<=num*num) {
				// 모든 배열 다 도달할 때까지
				snail[x][y] = n++; // 값 넣어주고 n 증가
				
				// 이동 예상 지점 확인해주는 과정
				nextX = x + dx[direction];
				nextY = y + dy[direction];
				if(nextX <0 || nextX>=num || nextY<0 || nextY>=num || snail[nextX][nextY]!=0) {
					// 배열 영역을 벗어나거나 이미 배열에 차있으면 방향 전환
					direction = (direction + 1) % 4;
				}
				// 진짜로 이동
				x = x + dx[direction];
				y = y + dy[direction];
				
			}
			
			// 전부 이동 후 
			System.out.printf("#%d", test_case);
			System.out.println();
			for(int i =0; i<num; i++) {
				for(int j = 0; j<num; j++) {
					System.out.print(snail[i][j] +" ");
				}
				System.out.println();
			}
		}
	}
}

 

번외: 토네이도

- 달팽이가 밖에서 안으로 들어간다면 토네이도는 안에서 밖으로 나오는 방법입니다. 

 

토네이도 모양으로 숫자를 채우기 위해서는 다음과 같은 알고리즘이 사용됩니다:

  1. 배열의 크기를 입력 받습니다.
  2. 중앙에서 시작하여 배열을 채우기 시작합니다.
  3. 각 숫자를 채우면서 이동 방향을 조절합니다. 이동 방향은 우측 → 하단 → 좌측 → 상단 순으로 이동합니다.
  4. 좌우로 이동하는 경우, 이동 거리를 1씩 증가시킵니다.
  5. 모든 배열을 채울 때까지 위 과정을 반복합니다.

아래는 코드 상에 있는 moveDistance가 왜 좌, 우로 가는 방향일 때 늘어나는지 알기 쉽게 그려본 그림이다. 

import java.util.Scanner;

class Solution
{
	public static void main(String args[]) throws Exception
	{
		
		Scanner sc = new Scanner(System.in);
		int T;
		T=sc.nextInt();
		
		for(int test_case = 1; test_case <= T; test_case++)
		{	
			// 배열의 크기를 입력 받음
			int num = sc.nextInt();
			int tornado[][] = new int [num][num]; // numxnum사이즈로 tornado 0으로 초기화
			
			int x = num/2; // 토네이도의 중앙
			int y = num/2; // 토네이도의 중앙을 시작 지점으로 설정
			
			int direction = 0; // 방향전환
			
			// 이동 규칙 벡터  우 하 좌 상
	        int[] dx = {0, 1, 0, -1};
	        int[] dy = {1, 0, -1, 0};
	        
	        // 배열에 넣을 값
	        int n = 1;
	        
	        int nextX = 0;
	        int nextY = 0;
	        
	        int filledCells = 0; // 채워진 칸 수
	        int moveDistance = 1; // 이동거리
	        while(n <= num*num) {
	        	// 모든 배열 다 돌면 끝남 // 홀수 배열일 때를 가정
	        	tornado[x][y] = n++; //넣고 1 증가
	        	filledCells++;
	        	
	        	//이동해주기
	        	x+=dx[direction];
	        	y+=dy[direction];
	        	
	        	// 각 방향으로 이동해야 한만큼 이동하면
	        	if(filledCells == moveDistance) {
	        		filledCells = 0; // 초기화
	        		// 방향 전환
	        		direction = (direction +1)%4;
	        		
	        		// 만약 좌, 우 방향이면 이동거리 증가
	        		 if (direction == 0 || direction == 2) {
	                        moveDistance++;
	                    }
	        	}
	        }

			
			
			// 전부 이동 후 
			System.out.printf("#%d", test_case);
			System.out.println();
			for(int i =0; i<num; i++) {
				for(int j = 0; j<num; j++) {
					System.out.print(tornado[i][j] +" ");
				}
				System.out.println();
			}
		}
	}
}