티스토리 뷰
https://www.acmicpc.net/problem/10997
#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행을 제외한 모든 행은 마지막이 *로 출력되기 때문에 문제가 되지 않는다!
이러면 예제와 같은 별 찍기를 할 수 있다!!!!!!!!!
'c언어 > BAEKJOON' 카테고리의 다른 글
c언어 15663번 N과 M (10) (백준) (0) | 2022.05.07 |
---|---|
c언어 15663번 N과 M (9) (백준) (0) | 2022.05.05 |
c언어 2580번 스토쿠 (백준) (0) | 2022.04.16 |
c언어 1003번 피보나치 함수 (백준) (0) | 2022.04.10 |
c언어 2447번 별찍기 - 10 (백준) (0) | 2022.04.10 |
- Total
- Today
- Yesterday
- 6198
- 최대공약수
- 스택
- DP
- java
- 1835번
- 그래프
- 트리
- 덱
- 6198번
- 카드
- 16120번
- C언어
- DFS
- Mo.s
- 오프라인 쿼리
- find
- BFS
- 정렬
- Krustal
- 누적합
- 세그먼트 트리
- 최소 스패닝 트리
- 1835
- 백준
- union
- C++
- 그리디
- 누적 합
- 플로이드
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |