[문제] 가로 6, 세로 5인 맵이 있다. (0, 0)에서 출발하여 (6, 5)에 가려고 한다.
단, 동일 가로행 및 세로열을 3회 이상 지나지 않는다고 할 때, 최장으로 갈 수 있는 이동거리는?
(동일 길을 2번 지나는 것은 가능하나, 각각 1번씩 카운트한다.)
예를 들어 아래 그림에서 첫번째 경로는 가능하고 (거리는 13) 두번째, 세번째 경로는 불가능하다.

[알고리즘]
각각의 가로행 및 세로열을 지난 횟수를 배열에 저장한다.
가로행은 총 6개 있으므로 cntX[6] 배열에 저장하고, 세로열은 총 7개 있으므로 cntY[7] 배열에 저장한다.
점이 (x, y)에서 (x + 1, y) 또는 (x -1, y)로 이동하면 cntX[y]가 1회 증가하고,
점이 (x, y)에서 (x, y+1) 또는 (x, y -1)로 이동하면 cntY[x]가 1회 증가한다.

cntX, cntY 내 원소들이 2가 넘지 않도록 하면서 이동한다.
아래는 코드
#include <stdio.h>
#define X 6
#define Y 5
int cntX[Y + 1] = { 0 };
int cntY[X + 1] = { 0 };
typedef struct point {
int x, y;
} point;
enum dir { E, W, S, N };
void solve(point* p, int* maxL, int depth);
void movePoint(point* p, int dir);
void returnPoint(point* p, int dir);
int main() {
point p = { 0, 0 };
int maxLength = 0;
int depth = 0;
solve(&p, &maxLength, depth);
printf("최장거리 = %d\n", maxLength);
}
void solve(point* p, int* maxL, int depth) {
if (p->x < 0 || p->x > X) // 경계 밖으로 벗어나면 리턴
return;
if (p->y < 0 || p->y > Y) // 경계 밖으로 벗어나면 리턴
return;
if (cntX[p->y] > 2 || cntY[p->x] > 2) // 2회 초과하여 지나가면 리턴
return;
if (p->x == X && p->y == Y) { // 목표 지점에 도달한 경우
*maxL = depth > *maxL ? depth : *maxL;
return;
}
// 동서남북 4개 방향 중 1가지 방향으로 이동한다.
for (int dir = E; dir <= N; dir++) {
movePoint(p, dir);
solve(p, maxL, depth + 1);
returnPoint(p, dir);
}
}
void movePoint(point* p, int dir) {
if (dir == E) {
p->x++;
cntX[p->y]++;
}
else if (dir == W) {
p->x--;
cntX[p->y]++;
}
else if (dir == S) {
p->y--;
cntY[p->x]++;
}
else {
p->y++;
cntY[p->x]++;
}
}
void returnPoint(point* p, int dir) {
if (dir == E) {
p->x--;
cntX[p->y]--;
}
else if (dir == W) {
p->x++;
cntX[p->y]--;
}
else if (dir == S) {
p->y++;
cntY[p->x]--;
}
else {
p->y--;
cntY[p->x]--;
}
}
정답은 25.

어떤 경로로 지나가는지 살펴보면 상당히 많은 경우의 수가 존재한다.



'프로그래밍 공부 > 알고리즘퍼즐68' 카테고리의 다른 글
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q50 동시에 끝나는 모래시계 (0) | 2026.07.01 |
|---|---|
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q49 완벽한 셔플 (0) | 2026.06.30 |
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q47 반전으로 만드는 엇갈리게 놓기 (0) | 2026.06.28 |
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q45 오직 하나뿐인 OX (0) | 2026.06.26 |
| c언어로 알고리즘퍼즐68 (프리렉) 풀기 Q44 정렬의 교환 횟수 최소화하기 (0) | 2026.06.25 |