달팽이
문제
홀수인 자연수 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 번호 적어가면서 풀었다.
- count를 가장 큰 수(n^2)부터 시작해서 1씩 빼면서 while loop을 돈다. count가 1이 되면 while loop을 빠져나올 것이다.
- while loop 안에서 현재 행열 번호의 자리에 숫자를 집어넣는다.
row, col을 1,1에서 시작하게 했기 때문에 snail에 집어넣을 때는 1씩 빼줬다. - 현재 자리의 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만큼만 이동함
- 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으로 숫자와 그 숫자일 때 어떤 행열번호가 나오는지 찍어보는 것을 추천한다.
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 14468 C# 소가 길을 건너간 이유 2 (2) | 2022.12.06 |
---|---|
[백준] 10816 C# 숫자 카드 2 (이분 탐색) (0) | 2022.12.05 |
[백준] 1026 C# 보물 (0) | 2022.11.15 |
[백준] 1920 C# 수 찾기 (0) | 2022.11.08 |
[백준] 10816 C# 숫자 카드 2 (0) | 2022.11.08 |
댓글