Post

웰노운 테크닉(추가 예정)

웰노운 테크닉

웰노운(진짜 웰노운)이지만, 따로 작성하기엔 양이 적은 테크닉들 모음.


상하좌우 탐색

(x, y)를 기준으로 상하좌우 좌표를 생각해보자. x의 변화량은 {-1, 1, 0, 0}이고, y의 변화량은 {0, 0, -1, 1}이다. 이것을 dx, dy배열로 만들어서 상하좌우 좌표를 계산하는 테크닉이다. 2차원의 4방향뿐만 아니라, N차원의 M방향은 전부 표현 가능하다.

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
bool visited[r][c];

void search(int x, int y) {
    for(int i = 0; i < 4; i++) {
        int nx = x + dx[i];
        int ny = y + dy[i];

        if(nx < 0 || nx >= r || ny < 0 || ny >= c || visited[nx][ny]) {
            continue;
        }

        visited[nx][ny] = true;
    }
}

벽 유무 판별

(일반적으로) 2차원 평면에서 상하좌우로 이동하려고 할 때, 벽의 존재여부를 판별하는 방법이다. 벽에 좌상우하 순서대로 각각 {1, 2, 4, 8}을 부여한다. 그리고 각 칸의 값은 칸에 존재하는 벽의 값의 합이다. 예를 들어서 4방향 전부 벽이 있다면 15, 하나도 없다면 0, 우하에 벽이 있다면 12가 칸의 값이다.

이제 비트마스킹을 통해 각 벽의 존재여부를 판별할 수 있다. 칸의 값과 각 벽의 값을 & 연산을 했을 때, 결과가 벽의 값과 같다면 벽이 존재하고, 0이면 벽이 존재하지 않는다.

벽에 부여하는 숫자의 값이나 순서는 임의대로 설정해도 상관없다.

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int r, c;
int board[50][50];
int wall_bit[4] = {1, 2, 4, 8};

void CheckWall() {
    for(int x = 0; x < r; x++) {
        for(int y = 0; y < c; y++) {
            for(int i = 0; i < 4; i++) {
                if((board[x][y] & wall_bit[i]) == wall_bit[i]) {
                    // exist wall
                }
            }
        }
    }
}

순열

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int n, r; // init
int arr[n] // init
bool visited[n]; 

void nPr(int depth) {
    if(depth == r) {
        for(int i = 0; i < n; i++) {
            if(visited[i]) {
                cout << i << " ";
            }
        }
        cout << '\n';
    }

    for(int i = 0; i < n; i++) {
        if(visited[i]) {
            continue;
        }

        visited[i] = true;
        nPr(depth + 1);
        visited[i] = false;
    }
}


조합

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int n, r; // init
int arr[n]; // init
bool visited[n]; 

void nCr(int depth, int last) {
    if(depth == r) {
        for(int i = 0; i < n; i++) {
            if(visited[i]) {
                cout << i << " ";
            }
        }
        cout << '\n';
    }

    for(int i = last; i < n; i++) {
        if(visited[i]) {
            continue;
        }

        visited[i] = true;
        nCr(depth + 1, i + 1);
        visited[i] = false;
    }
}

트리의 지름

트리의 지름

This post is licensed under CC BY 4.0 by the author.