이 글은 과제 제출 기한이 지났고 사이트 내에서 코드도 열람이 가능해졌기 때문에
풀이를 정리해도 될 것 같아 비공개 글에서 공개글로 전환하였습니다.
<안내>
필자도 배우는 입장이라 틀린점, 잘못된 점이 있을 수 있습니다.
그러니 지적, 피드백 환영합니다.
숫자 정사각형 만들기
숫자로 중앙에서부터
0
111
101
111
00000
01110
01010
01110
00000
이런식으로 0과 1이 왔다 갔다하는 도형을 만드는 문제다
풀이까지 가는 과정은 다음과 같다.
일단 100 * 100의 배열을 선언하고 (최대 크기일때도 크기가 넘치지 않는 배열),
그 배열을 0으로 초기화해줘(안에 있는 쓰레기 값을 처리하는 과정)
그러고 시작하는거.그러고 반복문에서 arr[][]을 채우는데, 윗칸, 아랫칸을 색칠할 때는, arr[고정][y--]로 했고,
좌 우를 돌릴땐, arr[y--][고정]으로 만들어서 루프를 돌려보았다.
#include <iostream> // 작동 안되는 코드
using namespace std;
int arr[100][100];
int main() {
int k, n, x, y, i, j;
int t;
cin >> t;
while(t--) {
cin >> n; // n 칸 짜리 배열을 만듬 근데 array특성상 빈칸은 일단 모두 0이지.
k = (n-1)/2; // k,k 가 중앙이 되도록 일단 짜고
for(int i = 0; i<=n;i++)
for(int j =0;j<=n; j++) arr[i][j] = 0;
for(x = 0; k >= 2 * x - 1 ; x++){ // 1을 넣는 부분임
for(y = 2 * x-1 ; y >= -(2 * x-1); y--) { // 0 을 1로 바꿔주는 작업
arr[k - (2 * x - 1)][k - y] = 1; // 윗칸
arr[k + (2 * x - 1)][k - y] = 1; // 아래칸
arr[k - y][k - (2 * x - 1)] = 1; // 왼졲칸
arr[k - y][k + (2 * x - 1)] = 1; // 오른쪽
}
}
for (i = 0; i < n; i++){
for (j = 0; j < n; j++) {
cout << arr[i][j];
}
cout << "\n";
}
}
}
숫자 정사각형 달팽이 모양 출력하기
처음엔 수학적 방법으로 접근했다가 아주 큰 코 다친 문제.
초기에 생각한 방법이다. 수학적 방법으로 어찌되었든 배열이 있으면 모든 부분은 나눌 수 있고,
나눠진 부분은 같은 역할을 하도록 만들면 돌릴 수 있다고 생각했다.
그러나 문제가 발생했다.
마지막 왼쪽 기둥의 진행이 끝나는 순간, 처음 루프로 돌아갔다.
마지막 왼쪽 기둥은 오른쪽으로 진행되어야 했는데,그 과정을 구현하지 않은것이다.
#include <iostream> // 작동 안되는 코드
using namespace std;
int arr[1000][1000];
int main() {
int a, b, i, j, n, x, y, cnt;
int t;
cin >> t;
while(t--) {
cin >> n >> a >> b;
cnt = 0; //카운트와 x, y 초기화
x = 1;
y = 1;
while (cnt <= b) {
if (cnt > a)
cout << (5*i+j) << " ";
func(x, y ,n,cnt);
}
cout << "\n";
}
}
int func(int i, int j, int n, int cnt) {
cnt++;
if (j >= i && i + j < n)
j++; // 함수아닌 버전의 윗줄의 처리에 해당
else if (j > i && i + j >= n)
i++; // 함수 아닌 버전의 오른쪽 열 처리에 해당
else if (j < i && i + j >= n)
j--; // 함수 아닌 버전 아랫줄 처리에 해당
else if (j <= i && i + j < n)
i--; // 함수 아닌 버전 왼쪽 열 처리에 해당
return cnt;
}
이리저리 찾아보고 고민하던 중, 문득 누군가가 말해주었던 방향배열이 생각났다 .
방향 배열이란 dx , dy란 배열을 만들어서 제어를 하는 방식이다.
코드를 한번 보도록 하자.
#include <iostream>
using namespace std;
int t, n, a, b;
int dy[] = { 0, 1, 0, -1 };
int dx[] = { 1, 0, -1, 0 };
int arr[1100][1100];
int main() {
cin >> t;
while(t--) {
cin >> n >> a >> b;
for(int i = 0; i <= 1010; i++) {
for(int j = 0; j <= 1010; j++) {
arr[i][j] = 0;
}
}
int y = 1;
int x = 1;
int d = 0;
for(int i = 1; i <= n * n; i++) {
arr[y][x] = i;
if(a <= i && i <= b) cout << (y - 1) * n + x << " ";
int next_x = x + dx[d];
int next_y = y + dy[d];
if(next_x <= 0 || next_x > n || next_y <= 0 || next_y > n || arr[next_y][next_x] != 0) {
d = (d + 1) % 4;
next_x = x + dx[d];
next_y = y + dy[d];
}
x = next_x;
y = next_y;
}
cout << "\n";
}
}
제일 먼저 모든 배열의 내용을 0으로 초기화하고, 달팽이처럼 행렬을 겉에서부터 배열을 채운다.
여기서 next_x와 next_y 만드는게 아주 중요한데, next_x는 단순히 x + 1이나 x + i같은 것이 아니라
x + dx[d] 를 해서 d가 바뀌면 계속 변화하도록 만들어준다.
만약 이 배열에서 끝을 만났거나, 이미 도착한 지점을 들어가면, d에 +1을 하고, 방향을 바꾸는 방식.
정말 강력한 방식이다.
이전에 오목 문제를 풀면서도 한번 접한 적이 있는 구조였는데, 이번 기회에 내 것으로 만들도록해야겠다.
'TIL > [C++ 프로그래밍} TIL' 카테고리의 다른 글
TIL (22.04.13) (0) | 2022.04.13 |
---|---|
TIL (22.04.11) (0) | 2022.04.11 |
TIL (22.04.03) (0) | 2022.04.08 |
TIL (22.04.06) (0) | 2022.04.06 |
TIL (22.04.04) (0) | 2022.04.04 |