목록으로
백준

BOJ - [Array - 10997 별찍기 - 22 ] - Silver II\U0001F948

문제 링크 문제 이름만 보면 우리가 흔히 온라인 저지에서 볼 수 있는 별찍기, 끽해봐야 조금 어려울 수 도 있는 별찍기에 불과하다고 생각할 수 있다. … 실제로도 그렇다. Source : GIPHY ??? 대신 이번에는 다른방법으로 문제를 풀어보기로 했다.

1분 읽기

문제

문제 링크

해설

문제 이름만 보면 우리가 흔히 온라인 저지에서 볼 수 있는 별찍기, 끽해봐야 조금 어려울 수 도 있는 별찍기에 불과하다고 생각할 수 있다.

실제로도 그렇다.

외부 임베드 Source : GIPHY

???

대신 이번에는 다른방법으로 문제를 풀어보기로 했다.

일반적으로 이런 별 찍기 문제를 푸는데는 주로 두가지 방법이 활용된다.

  1. 도화지에 그림을 그리듯 큰 배열을 두고 별의 규칙을 파악해 그 규칙에 맞춰 반복문을 통해 별을 찍는 방법
  2. 배열 없이 반복문을 돌리는 동시에 그대로 출력하는 방식

이번에 사용된 방법은 1번 방법의 심화판이라고 생각해도 좋을 듯 하다.

이번에는 포인터에 개념이 사용되었는데 포인터에 대한 자세한 개념은 추후에 다른문제를 풀면서 별도로 다뤄 보도록 하고 이번문제에 활용된 핵심 함수들을 소개하도록 하겠다.

memset - String.h 헤더에 포함

mem은 Memory(메모리)를 의미하며 특정 메모리 주소에 어떠한 값을 집어 넣을 때 사용되는 함수

sizeof - stdio.h 헤더에 포함

배열의 사이즈를 바이트 단위로 가져오는 함수이며 또 특정 자료형의 크기를 반환하도록 할 수 있는 함수 이다. 예) sizeof(int) → 4바이트 이므로 4를 반환

핵심 함수를 확인했으니 이제는 이번 문제를 푸는데 사용된 소스 코드를 확인해보자.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

int k=0, first_width, first_height,width,height,w_cursor=0,h_cursor=0;
bool arr[400][500],left_bottom = true;

void first_setup(int n) // 첫 준비 작업을 위한 함수
{
	first_width = width = 4*n-3;	//가로
	first_height = height = n != 1 ? 4*n-1 : 1;	//세로
	for(int i=0; i< (n == 1 ? 1 : height); i++)
		memset(arr[i],false,sizeof(bool)*(width));
	
	memset(arr[0],true,sizeof(bool)*width);
}
void set(int n)
{
	for(int k=0; height >= 3; k++)
	{
		if(k%2 == 1 && k > 0)
			h_cursor += 2;
		for(int i=0; i<height; i++)
			memset(arr[i+h_cursor]+(!left_bottom ? width+1 : first_width - width),true,sizeof(bool));
		memset(arr[left_bottom ? first_height-1-k: k+1] +w_cursor,true,sizeof(bool)*(first_width - (2*k)));
		height -= 2;
		if(k % 2 == 0)
			w_cursor += 2;
		left_bottom = !left_bottom;
		width = (!left_bottom) ? width - 2 : width;
	}
}
int main()
{
	int n;
	scanf("%d",&n);
	first_setup(n);
	set(n);
	for(int i=0; i<first_height; i++) // 출력
	{
		for(int j=0; j<first_width; j++)
		{
			if(i != 1)
				printf("%c",arr[i][j] == true ? '*' : ' ');
			else if(arr[i][j] == true)
				printf("*");
		}
			
		printf("\n");
	}
    return 0;
}

이번 소스코드도 memset을 처음 활용해보려고 하다보니까 시간도 더 소요됐고 최종적으로 풀기는 했지만 결국 스파게티 코드의 형태가 되어 버린것 같지만 일단 하나하나 이 소스코드의 원리를 설명 해 보도록 하겠다.

별찍기 규칙?

위 사진은 n=3일 때 별이 찍힌모습을 보여주고 있다. 여기서 n은 얼마나 감겼나를 의미하며, 중심 별을 기준으로 바깥쪽까지 총 3겹으로 이루어져 있는 것으로 확인 할 수 있다.

이 두 개도 같이 살펴보면 더 분명히 알 수 있다.

별을 찍을 순서를 생각해 보면….

Untitled

위 사진 처럼 1번, 2번과정을 계속반복하게 되면 안쪽으로 들어가면서 이 과정이

계속 이어지게 된다.

주의사항 (?)


  • ←여기는 두번째 줄은 절대 공백을 삽입하면 안된다. 채점할때 틀린것으로 처리된다.

이번코드는 memset함수 활용하는 것에 아직 익숙하지 못해 번잡한 코드를 작성하게 된 것 같은데 기회가된다면 조금더 소스코드를 다듬어서 다시 풀어보는 것도 괜찮을 것 같다.

댓글