codingtest

1987번 - 알파벳

2024-01-31
3분 분량
C++백준

문제 링크

문제 풀이 시간 : 1시간

문제 요약

  • 보드의 각 칸에는 알파벳이 있음
  • 주변의 네 칸 중 다른 칸으로 이동한다.
  • 새로 이동한 칸은 지금까지 지나온 알파벳이 아니어야 함.
  • 최대로 갈 수 있는 칸 수 구하기

문제 풀이

이 문제는 간단하게 DFS로 풀 수 있겠다고 생각했다.

초기 코드

c++
#include <iostream>
#include <vector>
#include <string>

using namespace std;

char board[21][21];
int arr[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
int r, c, ans;

bool check(int x, int y) { //보드를 넘어가는지 확인
    if ((x >= 0 && x < r) && (y >= 0 && y < c))
        return true;
    else
        return false;
}

void find(bool visited[21], int x, int y, int sum) { //DFS함수
    int tx, ty;
    ans = max(sum, ans); //현재 값이 최댓값보다 크면 교체
		visited[board[x][y] - 'A'] = true; //방문 처리
    for (int i = 0; i < 4; i++) { //주변 칸 탐색
        tx = x + arr[i][0]; 
        ty = y + arr[i][1];

        if (check(tx, ty)) { //보드를 넘어가지 않으면
            if (!visited[board[tx][ty] - 'A']) { //방문되지 않았다면
                find(visited, tx, ty, sum + 1); 
            }
        }
    }
}

int main() {
    string input;
    cin >> r >> c;
    for (int i = 0; i < r; i++) {
        cin >> input;
        for (int j = 0; j < c; j++)
            board[i][j] = input[j];
    }
    bool visited[21] = {false};
    visited[board[0][0] - 'A'] = true;
    find(visited, 0, 0, 1);
    cout << ans;
}

위 코드는 아쉽게도 바로 틀렸다고 한다.

이유가 무엇일까?

이유는 이미 방문 했더라도 다른 경우가 있을 수 있기 때문에 방문 후 다시 방문하지 않았다고 해주어야 한다.

아래와 같은 경우를 보자.

post image

(0,0)에서 시작하므로 갈 수 있는 칸은 (1,0)과 (0,1)이다.

이때 만약 (1,0)으로 간다면 (2,0)과 (1,1) 모두 이미 방문한 것이므로 이동 횟수는 2이다.

post image

하지만 (0,0)에서 (0,1)로 이동한다면 아래와 같이 4가 나온다.

post image

따라서 다른 칸으로 방문한 후 visited를 다시 false로 바꿔주어 주변의 다른 칸에 같은 알파벳이 있어도 방문할 수 있도록 해주어야한다.

최종 코드

c++
#include <iostream>
#include <algorithm>

using namespace std;

char board[21][21];
int arr[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
int r, c, ans;

bool check(int x, int y) { //보드를 넘어가는지 확인
    if (x >= 0 && x < r && y >= 0 && y < c)
        return true;
    else
        return false;
}

void find(bool visited[27], int x, int y, int sum) { //DFS함수
    int tx, ty;
    if (ans < sum) //현재값이 최댓값보다 크면 교체
        ans = sum;
    for (int i = 0; i < 4; i++) { //주변 칸 탐색
        tx = x + arr[i][0];
        ty = y + arr[i][1];

        if (check(tx, ty)) { //보드를 넘어가지 않고
            if (!visited[board[tx][ty] - 'A']) { //방문하지 않았다면
                visited[board[tx][ty] - 'A'] = true; //방문 처리
                find(visited, tx, ty, sum + 1); //DFS 호출
                visited[board[tx][ty] - 'A'] = false; //방문 취소
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin >> r >> c;
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++)
            cin >> board[i][j];
    }
    bool visited[27] = {false};
    visited[board[0][0] - 'A'] = true;
    find(visited, 0, 0, 1);
    cout << ans;
}

함께 읽으면 좋은 글