본문 바로가기
알고리즘/백준

[백준] 1913 C# 달팽이

by 개발하는 디토 2022. 11. 15.

달팽이

 

문제

홀수인 자연수 N이 주어지면, 다음과 같이 1부터 N2까지의 자연수를 달팽이 모양으로 N×N의 표에 채울 수 있다.

9 2 3
8 1 4
7 6 5

 

25 10 11 12 13
24 9 2 3 14
23 8 1 4 15
22 7 6 5 16
21 20 19 18 17

N이 주어졌을 때, 이러한 표를 출력하는 프로그램을 작성하시오. 또한 N2 이하의 자연수가 하나 주어졌을 때, 그 좌표도 함께 출력하시오. 예를 들어 N=5인 경우 6의 좌표는 (4,3)이다.

입력

첫째 줄에 홀수인 자연수 N(3 ≤ N ≤ 999)이 주어진다. 둘째 줄에는 위치를 찾고자 하는 N2 이하의 자연수가 하나 주어진다.

출력

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

예제 입력 1

7
35

예제 출력 1

49 26 27 28 29 30 31
48 25 10 11 12 13 32
47 24 9 2 3 14 33
46 23 8 1 4 15 34
45 22 7 6 5 16 35
44 21 20 19 18 17 36
43 42 41 40 39 38 37
5 7

 

 

내 풀이

dirCount   6 5 4 3 2 1  
1 49 26 27 28 29 30 31 7
2 48 25 10 11 12 13 32 6
3 47 24 9 2 3 14 33 5
4 46 23 8 1 4 15 34 4
5 45 22 7 6 5 16 35 3
6 44 21 20 19 18 17 36 2
7 43 42 41 40 39 38 37 1
  1 2 3 4 5 6 7  

 

달팽이류 문제는 direction을 바꿔가며 행 열 번호를 늘리고 줄이고 하면서 푸는 것 같다. 열심히 메모장에 index 번호 적어가면서 풀었다.

  1. count를 가장 큰 수(n^2)부터 시작해서 1씩 빼면서 while loop을 돈다. count가 1이 되면 while loop을 빠져나올 것이다.
  2. while loop 안에서 현재 행열 번호의 자리에 숫자를 집어넣는다.
    row, col을 1,1에서 시작하게 했기 때문에 snail에 집어넣을 때는 1씩 빼줬다.
  3. 현재 자리의 dirCount와 limit을 비교해 방향을 변경해야 하는 자리인지 판단한다.  
    • dirCount=0에서 시작하므로 1 증가시켜야 현재 자리의 dirCount이다.
    • dirCount와 limit으로 방향을 바꿔야 할 때를 판단한다.
    • left -> down으로 바뀔 때와 그렇지 않을 때로 나뉜다.
      • 보통은 dirCount를 1로 초기화하고 dir만 1 늘려주면 된다.
      • left -> down으로 바뀔 때는 한 줄 안으로 들어가므로 limit에서 2를 빼준다. dirCount를 0으로 초기화하는 이유는 left -> down으로 바뀔 때 한줄 더 내려가야 해서 일부러 dirCount를 1 작게 잡아주는 것이다.
        ex) 26 -> 21로 내려갈 때 5만큼 이동하지만 21-> 17, 17->13, 13->10 으로 갈 때는 4만큼만 이동함
  4. dir 값에 따라 다음 행열 번호를 지정한다.
    • 어차피 down -> right -> up -> left 순서로만 이동하므로 방향을 바꿀 때 dir를 1씩 늘리고 나머지 연산으로 현재 이동하는 방향을 판단한다.

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Baekjoon
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = int.Parse(Console.ReadLine());
            int numToFind = int.Parse(Console.ReadLine());

            int row=1, col=1;
            int dir = 0; // down0 right1 up2 left3 
            int count = n*n; // starts from n^2
            int dirCount = 0;
            int limit = n;

            int[,] snail = new int[n,n];
            int frow = 0, fcol = 0;

            while (true)
            {
                //Console.WriteLine($"count {count}: {row} {col}");
                snail[row - 1, col - 1] = count;
                if (count == numToFind) { frow = row; fcol = col; }
                if (count == 1) break;
                dirCount++;

                count--;

                // direction change
                if (dir % 4 == 3 && dirCount == limit - 1)
                {
                    limit -= 2; // Limit은 왼쪽에서 아래로 방향 바뀔 때 바뀌어야 함
                    dir++;
                    dirCount = 0; // left->down으로 바뀔 때만 한 칸 더 내려가야 하므로
                }
                else if (dirCount == limit)
                {
                    dirCount = 1;
                    dir++;
                }

                if (dir % 4 == 0) row++;      // down
                else if (dir % 4 == 1) col++; // right                
                else if (dir % 4 == 2) row--; // up
                else if (dir % 4 == 3) col--; //left

            }

            StringBuilder sb = new StringBuilder();
            for(int i = 0; i<n; i++)
            {
                for (int j=0; j<n; j++)
                {
                    sb.Append($"{snail[i,j]} ");
                }
                sb.Append("\n");
            }
            Console.Write(sb);
            Console.WriteLine($"{frow} {fcol}");
        }
    }
}

 

후기

실버 3에도 헷갈리는 나란 녀석... 수련이 더 필요하다.

헷갈리면 Console.WriteLine으로 숫자와 그 숫자일 때 어떤 행열번호가 나오는지 찍어보는 것을 추천한다.

댓글