4 X 4 매트릭스에 O 또는 X가 채워져 있다. 그리고 각 행과 열에 O의 개수를 카운트한다. (아래 그림 참조)

위 매트릭스는 1111, 1111 2개의 숫자로 표현할 수 있다.
그런데, 아래 배열 역시 동일하게 1111, 1111로 표현할 수 있다.

이런 경우, 위 2개의 매트릭스는 서로 형제 관계에 있다고 하자.
(1111, 1111이라는 동일한 부모 숫자를 가지므로)
[문제] 형제가 없는, 즉 외동인 OX 배열의 개수는?
예를 들면 아래 배열은 3211, 4201로 나타낼 수 있는 유일한 배열이므로 외동이다.

[알고리즘]
먼저 제일 간단한 케이스인 2 X 2 매트릭스에 대해서 살펴보자.
아래 2개의 배열은 서로 형제이다.

위 케이스에 대해서만 형제이고, 나머지 배열들은 모두 외동이다.
이제 2 X 3 매트릭스에 대해서 살펴보자.

위 물음표에 뭐가 오든지 위 배열은 형제가 존재한다.
아래 배열도 마찬가지.

3 X 3 매트릭스에 대해서 살펴보자. 아래 배열 역시 ?에 뭐가 오든 형제가 존재한다.

아래 배열 등도 마찬가지

이를 일반화하면

임의의 row1, row2, col1, col2에 대해서
matrix[row1][col1] != matrix[row1][col2] 이면서
matrix[row1][col1] != matrix[row2][col1] 이면서
matrix[row2][col1] != matrix[row2][col2] 이면
형제가 존재한다.
이런 경우를 제외하고 카운트하면 된다.
아래는 코드.
#include <stdio.h>
#include <stdbool.h>
#define N 4
int matrix[N][N] = { 0 };
int cnt = 0;
void solve(int matrix[][N], int row, int col);
bool checkMatrix(int matrix[][N]);
int main() {
solve(matrix, 0, 0);
printf("cnt = %d\n", cnt);
}
void solve(int matrix[][N], int row, int col) {
if (row == N) {
if (checkMatrix(matrix) == true)
cnt++;
return;
}
for (int i = 0; i <= 1; i++) {
matrix[row][col] = i;
if (col == N - 1)
solve(matrix, row + 1, 0);
else
solve(matrix, row, col + 1);
}
}
bool checkMatrix(int matrix[][N]) {
int row1, row2;
int col1, col2;
for (row1 = 0; row1 < N - 1; row1++) {
for (row2 = row1 + 1; row2 < N; row2++) {
for (col1 = 0; col1 < N - 1; col1++) {
for (col2 = col1 + 1; col2 < N; col2++) {
if (matrix[row1][col1] == matrix[row1][col2])
continue;
if (matrix[row1][col1] == matrix[row2][col1])
continue;
if (matrix[row2][col1] != matrix[row2][col2])
return false;
}
}
}
}
return true;
}
정답은 6902개.

그런데 위 코드는 4 x 4칸을 모두 채운 후에 매트릭스를 검사하기 때문에 시간이 오래 걸린다.
매트릭스를 채워나가는 족족 바로바로 검사를 해서 걸러내면 시간을 단축시킬 수 있다.
아래와 같이 함수를 수정하면 된다.
void solve(int matrix[][N], int row, int col) {
if (row == N) {
cnt++;
return;
}
for (int i = 0; i <= 1; i++) {
matrix[row][col] = i;
if (col == N - 1) {
if (checkMatrix(matrix, row) == false) // row가 모두 채워지면 검사
continue;
solve(matrix, row + 1, 0);
}
else
solve(matrix, row, col + 1);
}
}
bool checkMatrix(int matrix[][N], int row) {
int row1, row2;
int col1, col2;
for (row1 = 0; row1 <= row - 1; row1++) {
for (row2 = row1 + 1; row2 <= row; row2++) {
for (col1 = 0; col1 < N - 1; col1++) {
for (col2 = col1 + 1; col2 < N; col2++) {
if (matrix[row1][col1] == matrix[row1][col2])
continue;
if (matrix[row1][col1] == matrix[row2][col1])
continue;
if (matrix[row2][col1] != matrix[row2][col2])
return false;
}
}
}
}
return true;
}
'프로그래밍 공부 > 알고리즘퍼즐68' 카테고리의 다른 글
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q48 급할수록 돌아가라 (0) | 2026.06.29 |
|---|---|
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q47 반전으로 만드는 엇갈리게 놓기 (0) | 2026.06.28 |
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q44 정렬의 교환 횟수 최소화하기 (0) | 2026.06.25 |
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q43 소수 매트릭스 (0) | 2026.06.24 |
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q42 유리컵 속 물을 반으로 (0) | 2026.06.22 |