문제 출처

1. 문제설명


  • 문제 설명이 길어, 요약하겠다.
  • N*M 크기의 보드판이 있고, 각 칸에는 알파벳 문자가 하나씩 적혀있다.
  • 시작하는 격자의 알파벳을 기준으로 어떤 문자열을 만들 수 있는 경우의 수를 찾는다.
    • 어떤 문자열은 같은 게 다시 등장할 수 있다.
  • 문자열을 이어붙일 때는 상,하,좌,우,대각선 방향으로 1칸씩 이동가능하다.
  • Out of Map(OOM) 시 반대 방향으로 이동하게 된다.



2. 알고리즘 설계


  • DFS 문제라고 생각했다.
  • 문제를 읽어보면, target 값이 재등장할 가능성이 있다.
    • map으로 경우의 수를 저장해두면, DP의 효과가 있다.
  • 이 문제의 경우 OOM의 처리를 안하고, 환형으로 본다.
    • 현재 좌표값에서 다음 좌표값, x의 길이를 더하고 x의 길이로 나눠주면 된다.
    • 이렇게 하면 환형 처리를 if문 없이 할 수 있다.
    • nx = (x + dx[dir] + x_len) % x_len
  • 보드판의 최대 크기가 10, target의 최대 길이는 5이므로
  • 구할 수 있는 모든 경우를 전부 미리 구해 놓는 방식을 채택하였다.



3. 전체 코드


#include <bits/stdc++.h>
using namespace std;

int n, m, k;
string target, board[10];
unordered_map<string, int> cnt;

const int dx[8] = {-1,-1,-1,0,0,1,1,1};
const int dy[8] = {-1,0,1,-1,1,-1,0,1};

void dfs(int y, int x, string s) {
    cnt[s]++;
    if(s.size() == 5) return;

    for(int dir=0; dir<8; dir++) {
        int ny = (y + dy[dir] + n) % n;
        int nx = (x + dx[dir] + m) % m;

        dfs(ny, nx, s + board[ny][nx]);
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n >> m >> k;
    for(int i=0; i<n; i++) cin >> board[i];

    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
            dfs(i, j, string(1, board[i][j]));

    while(k--) {
        cin >> target;
        cout << cnt[target] << '\n';
    }

    return 0;
}