티스토리 뷰

https://www.acmicpc.net/problem/10997

 

10997번: 별 찍기 - 22

예제를 보고 규칙을 유추한 뒤에 별을 찍어 보세요.

www.acmicpc.net

 

#include <stdio.h>

char map[400][400]; //*을 담을 배열

void loop(int k, int n)
{
	if(k==n-1) return; //* 제거 완료
    
	int key = 2*k+1;

	for(int i = key; i<=(n-1)*4-k*2; i++)
	{
		map[key][i] = 32;
		map[i+1][key] = 32;
	}
	
    for(int i = key; i<=(n-1)*4-2*k-1; i++)
	{
		map[4*n-2*k-3][i] = 32; 
		map[i+2][4*(n-1)-2*k-1] = 32;
	}
	
	loop(k+1, n); // ex) n=3이면 k = 0 -> 1 -> 2(여기서 return;)
}

int main(void)
{
	int n = 0;
	scanf("%d", &n); // n 입력 받기
	if(n==1) {//n==1
		printf("*");
		return 0;
	}
	
	int key = 4*(n-1); 
	for(int i = 0; i<key+3; i++) //출력할 모든 영역에 *을 대입
	for(int j = 0; j<key+1; j++)
	map[i][j] = 42; //ASCII * 42(10진수), 공백 32(10진수)
	
	loop(0, n); //input space //* 제거
	
	for(int i = 0; i<key+3; i++) { //남은 * 출력
		if(i==1) printf("%c\n", map[1][0]);
		else printf("%s\n", map[i]);
	}

	return 0; //종료
}

 

  • 설명

1. 처음에 수를 입력받으면, 출력할 곳을 다 * 로 가득 채워놓는다. 그다음 *을 제거하여 예제와 같이 나오도록 만든다.

 

2. 출력 할 곳의 크기 :  행(가로)은 4*(n-1)+1  열(세로)은 4*(n-1)+3이다. 

예)

n == 2 :    5 *   7

n == 3 :    9 * 11

n == 4 : 13 * 15

 

3.  재귀함수 또는 while문을 이용하여, 빈칸 만들기.

빈칸은 0 또는 32를 대입하여 각각 \0    공백으로 만들 수 있다. (원하는 걸 넣자)

 

일단 빨강으로 표시 된 부분부터 공백으로 만들어 보자. (n == 2)

 
 
   

이는 가로 세로로 쪼개서 이렇게 같은 개수의 두 개의 부분으로 나눌 수 있으며(빨간색, 노란색)

 

 
 
   

 

n == 3 에서는 (파란색 배경은 n == 2의 부분이다)

 

 
 
 
 
 
 
           

 

n==2에서는 빨강 : 4, 노랑 4

n==3에서는 빨강 : 8, 노랑 8

n==4에서는 빨강 : 12, 노랑 12 이므로 반드시 두 번째 행에서는 별을 4*(n-1) 개 씩을 지워야 한다. 

 

또한 n==3을 보면 

내부모습이 n==2와 같음을 알 수 있다. (그래서 while 또는 재귀 함수로 한다)

 

코드

int key = 2*k+1

for(int i = key; i<=(n-1)*4-k*2; i++)
{
map[key][i] = 32;
map[i+1][key] = 32;
}

풀이 : n==3 일 때, key = 1, (n-1)*4-k*2 = 8 이므로 8번 반복. 

        map[key][i] = 32;  가로로 이동하면서 공백을 만듦

        map[i+1][key] = 32; 세로로 이동하면서 공백을 만듦

        초기값  가로 : map[1][1], 세로 : map[2][1]

 

        그다음 loop(k+1, n)으로 들어온 뒤 

        key = 2*k +1 = 3, (n-1)*4-k*2 = 6 이므로 4번 반복.

        map[key][i] = 32;  가로로 이동하면서 공백을 만듦

        map[i+1][key] = 32; 세로로 이동하면서 공백을 만듦

        초기값  가로 : map[3][3], 세로 ; map[4][3]

 

가로의 초기값들은 2*k+1을 따른다! 

 

         그 다음 loop(k+1, n)으로 들어온 뒤

         k==n-1 (둘 다 2)으로 인해 재귀 함수 종료

 

 

이제 나머지 부분도 제거해보자 (이미 제거한 부분도 있다!)

 

 

이것도 두 부분으로 나누면 가로로 연속된 것과, 세로로 연속된 것으로 나눌 수 있다.

 

       
 
 
 

 

n == 3에서도 보면...

 

 

보라색이 6개에서 2개, 청색도 6개에서 2개로 바뀌는 모습을 볼 수 있다.

여기도 똑같이 재귀 또는 반복할 때마다, for문 내부가 돌아가는 횟수를 4만큼 계속 감소해 주면 된다!

 

코드

 for(int i = key; i<=(n-1)*4-2*k-1; i++)
{
map[4*n-2*k-3][i] = 32; 
map[i+2][4*(n-1)-2*k-1] = 32;
}

 

 

풀이 : n==3 일 때, key = 1, (n-1)*4-2*k-1 = 7 이므로 7번 반복 

        map[4*n-2*k-3][i] = 32;  가로로 이동하면서 공백을 만듦

        map[i+2][4*(n-1)-2*k-1] = 32; 세로로 이동하면서 공백을 만듦

        초기값  가로 : map[9][1], 세로 : map[3][7]

        위에서는 6번 반복이라고 했으나, for문은 7번 반복이다!, 그러나, 가로의 초기값은 이미 공백으로 바뀐 곳이며,

        세로의 초기값(장소)도 map[4*n-2*k-3][i] = 32; 에 의해 공백으로 바뀐 곳이므로, 실질적으로는 6개의 공백들을          만들게 된다!

 

loop(k+1, n) 실행

        

        n==2 일 때, key = 3, (n-1)*4-2*k-1 = 5 이므로 3번 반복

        map[4*n-2*k-3][i] = 32;  가로로 이동하면서 공백을 만듦

        map[i+2][4*(n-1)-2*k-1] = 32; 세로로 이동하면서 공백을 만듦

        초기값  가로 : map[7][3], 세로 : map[5][5]

        위에서는 2번 반복이라고 했으나, for문은 3번 반복이다!, 그러나, 가로의 초기값은 이미 공백으로 바뀐 곳이며,

        세로의 초기값(장소)도 map[4*n-2*k-3][i] = 32; 에 의해 공백으로 바뀐 곳이므로, 실질적으로는 2개의 공백들을          만들게 된다!

       

그다음 loop(k+1, n)으로 들어온 뒤

         k==n-1 (둘 다 2)으로 인해 재귀 함수 종료

 

이렇게 되면 원하는 모양의 별들만을 남길 수 있게 된다.

이는 n==2, n==3말 고도 그 이상의 것도 다 적용된다! (점화식으로 만들었기 때문이다!)

 

4. 출력

이제 char map[400][400] 중 출력할 영역을 printf() 하면 되나, 주의할 점이 있다.

 

모든 예제의 2번 행(가로)을 보면 * 하나만 달랑 있다.

이는 * 하나만 출력해야 된다.

그러나 내가 만든 코드는 공백으로 *을 바꾸었기 때문에, 공백이 출력되고 만다. (이는 오류로 처리된다)

그러므로 

 

코드

 

for(int i = 0; i<key+3; i++) { //남은 * 출력
if(i==1) printf("%c\n", map[1][0]);
else printf("%s\n", map[i]);
}

 

풀이

if(i==1) printf("%c\n", map[1][0]);  // 2행은 맨 처음 값만 출력한다!

나머지 행들은 다 출력한다. 왜냐면 2행을 제외한 모든 행은 마지막이 *로 출력되기 때문에 문제가 되지 않는다!

 

이러면 예제와 같은 별 찍기를 할 수 있다!!!!!!!!!

최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함