문제 : https://www.acmicpc.net/problem/1194


비트마스킹 BFS 그래프탐색

[문제해석]

 

  '0' 지점에서 '1' 지점까지 탐색을 진행하는데 'a','b','c','d','e','f' 는 열쇠고 'A','B','C','D','E','F'는 각각 소문자 열쇠로 열 수 있는 문이다. 문을 열려면 열쇠가 있는 지점을 먼저 방문해서 열쇠를 가지고 방문해야된다.

 

[알고리즘풀이]

 

 전형적인 비트마스킹을 활용한 그래프 탐색 문제로 열쇠가 6 종류 밖에 없는 점에 집중해 비트마스킹으로 현재 어떤 열쇠들을 가지고 있는지 표현해주면 된다. 

 visited[X][Y][curS] := (X, Y) 지점에 curS 열쇠 상태로 방문했을 때 최소 이동 횟수 라고 정의하면 문제를 쉽게 해결할 수 있다.

 

 1) 다음에 이동할 지점이 '.' 거나 '1' 이면 현재 이동 횟수 + 1 이 해당 지점에 현재 상태로 방문한 가장 작은 값이라면 이동을 진행한다.

 

 2) 다음에 이동할 지점이 열쇠가 있고 현재 이동 횟수 + 1 이 해당 지점에 현재 상태로 방문한 가장 작은 값이라면 이동을 진행한다. 그 후, 현재 상태에 해당 지점의 열쇠를 갱신해준다.

 | (OR) 연산을 이용하면 쉽게 갱신할 수 있다.

 ( curS | (1 << key) ) 

 

 3) 다음에 이동할 지점이 문이 있고 현재 이동 횟수 + 1 이 해당 지점에 현재 상태로 방문한 가장 작은 값이고, 현재 열쇠 상태가 해당 문을 열 수 있다면 이동을 진행한다.

 & (AND) 연산을 이용하면 현재 열쇠 상태로 문을 열 수 있는지 쉽게 확인할 수 있다.

 ( curS & (1 << door) )

 

[ 주의사항 ]

 

 열쇠가 총 6종류 이므로 비트마스킹을 (1 << 7) 로 진행해야되는데, (1 << 6) 으로 셋팅해서 개고생을 했다....! 조심, 또 조심!

 

[ 정답코드 ]

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include<iostream>
#include<queue>
using namespace std;
 
struct position {
    int x, y, s, l;
};
 
const int INF = 9999999;
int r, c;
int visited[50][50][1 << 7];
int dx[4= { -1010 }, dy[4= { 0-101 };
char map[50][51];
 
bool checkIndex(int x, int y) {
    return (0 <= x && x < r && 0 <= y && y < c);
}
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
 
    cin >> r >> c;
    for (int i = 0; i < r; i++)
        cin >> map[i];
    for (int i = 0; i < r; i++) // 초기화
        for (int j = 0; j < c; j++)
            for (int k = 0; k < (1 << 7); k++)
                visited[i][j][k] = INF;
 
    queue<position> q;
    for (int i = 0; i < r; i++) // 시작점 찾기
        for (int j = 0; j < c; j++)
            if (map[i][j] == '0') {
                visited[i][j][0= 0;
                q.push({ i, j, 00 });
                map[i][j] = '.';
            }

    while (!q.empty()) { // 탐색진행
        int curX = q.front().x, curY = q.front().y, curS = q.front().s, curL = q.front().l;
        q.pop();
        if (map[curX][curY] == '1'continue;
 
        for (int i = 0; i < 4; i++) {
            int nextX = curX + dx[i], nextY = curY + dy[i];
            if (!checkIndex(nextX, nextY)) continue;
            if (map[nextX][nextY] == '#'continue;
            if ((map[nextX][nextY] == '.' || map[nextX][nextY] == '1'&& curL + 1 < visited[nextX][nextY][curS]) { // 그냥 갈 수 있는 길
                visited[nextX][nextY][curS] = curL + 1;
                q.push({ nextX, nextY, curS, curL + 1 });
            }
            else if ('a' <= map[nextX][nextY] && map[nextX][nextY] <= 'f' && curL + 1 < visited[nextX][nextY][curS]) {
                int key = (map[nextX][nextY] - 'a'+ 1;
                visited[nextX][nextY][curS] = curL + 1;
                q.push({ nextX, nextY, curS | (1 << key), curL + 1 });
            }
            else if ('A' <= map[nextX][nextY] && map[nextX][nextY] <= 'F' && curL + 1 < visited[nextX][nextY][curS]) {
                int door = (map[nextX][nextY] - 'A'+ 1;
                if (curS & (1 << door)) {
                    visited[nextX][nextY][curS] = curL + 1;
                    q.push({ nextX, nextY, curS, curL + 1 });
                }
            }
        }
    }
    
    int ans = INF; // '1' 인 지점에 방문한 값 중 최소값 찾기
    for (int i = 0; i < r; i++)
        for (int j = 0; j < c; j++)
            if (map[i][j] == '1')
                for (int k = 0; k < (1 << 7); k++)
                    ans = min(ans, visited[i][j][k]);
    if (ans == INF) ans = -1;
    cout << ans << '\n';
}
cs

 

'Problem Solving > BOJ' 카테고리의 다른 글

[BOJ] 2517 : 달리기  (0) 2020.08.14
[BOJ] 10167 : 금광  (0) 2020.08.13
[BOJ] 17025 : Icy Perimeter  (0) 2020.07.30
[BOJ] 15898 : 피아의 아틀리에 ~신비한 대회의 연금술사~  (0) 2020.07.27
[BOJ] 15906 : 변신 이동 게임  (0) 2020.07.06

이클립스랑 톰캣을 정상적으로 설치하고 연동 후 Hello-World 를 띄우려니까 아래와 같은 에러가 발생했다.

구글링을 해보니 Tomcat 서버 포트를 지정하지 않아서 그렇다는 것 같다. 해결방법은 간단하다. Tomcat 서버 포트를 지정해주면 된다.

 

[01] 이클립스의 하단 Servers에 "Tomcat v9.0 Server at localhost" 를 더블클릭한다.

[02] Tomcat admin port 의 Port Number를 8005 나 8080 으로 지정해주면 된다.

처음에는 Port Number가 지정되지않고 "-" 로 적혀있었다.

 

MySQL을 설치 후 HeidiSQL을 통해 MySQL 명령어를 입력했더니 다음과 같은 오류가 발생했습니다.

구글링을 해보니 MySQL 을 설치하고 root 계정의 비밀번호가 임의로 변경되어, 다시 새롭게 root 계정의 비밀번호를 설정하면 해결할 수 있는 에러였습니다.

 

[01] MySQL을 실행하고 다음과 같은 명령어를 입력한다. 새로운 비밀번호는 8글자 이상이고 대문자 소문자 숫자 특수문자를 포함해야된다고 합니다.

1
alter user 'root'@'localhost' identified by '새로운비밀번호';
cs

[02] 다음 명령어를 추가로 입력한다.

1
commit;
cs

 

그럼 root 계정의 비밀번호가 변경되고 에러가 해결됩니다.

 

HeidiSQL은 MySQL 자체에서 제공하는 비주얼 툴보다 다루기 쉬운 비주얼 툴입니다. HeidiSQL 설치 및 다운로드에 대해서 포스팅 해보겠습니다.


[01] 다운로드를 위해 사이트로 이동합니다. Downloads 메뉴의 Installer 로 이동합니다.

https://www.heidisql.com/download.php?download=installer

[02] Installer, 32/64 bit combined 를 클릭해 다운로드 받습니다.

[03] HeidiSQL_11.0.0.5919_Setup.exe 파일을 실행합니다.

[04] I accept the agreement를 클릭하고 [Next]를 클릭합니다.

[05] 기본값을 유지하며 [Next]를 클릭합니다.

[06] 가벼운 비쥬얼툴이므로 설치가 금방 완료됩니다.

[07] 설치가 제대로 완료되었는지 확인합니다. HeidiSQL은 MySQL Command Line Client 보다 훨씬 더 다루기 쉽고 보기 편합니다.


 

 DBMS 중 개발용으로는 무료로 사용 가능한 MySQL 설치 및 다운로드에 대해서 포스팅해보겠습니다.


[01] https://dev.mysql.com/downloads/installer/ 에 접속해 MySQL 버전 8을 다운로드합니다.

[02] 파일을 다운로드하기 위해 오라클 회원가입 및 로그인을 해줍니다.

 

[03] 파일을 다운로드합니다.

[04] mysql-installer-community-8.0.21.0.exe 파일을 실행합니다.

[05] 개발용으로 사용할 것이기 때문에 Server only 로 다운로드합니다.

[06] [Execute] 를 실행합니다.

[07] Status가 Complete로 바뀌면 [Next]를 누릅니다.

[08] [Next]를 누릅니다.

[09] Standalone MySQL Server / Classic MySQL Replication 을 선택하고 [Next]를 누릅니다.

[10] ConfigType과 Port를 설정하는 부분입니다. 기본값으로 설정하고 [Next]를 누릅니다.

[11] Password를 사용하는 인증방식을 선택하고 [Next]를 누릅니다.

[12] Root 계정의 비밀번호를 설정한 후 [Next]를 누릅니다.

[13] 기본값으로 설정하고 [Next]를 누릅니다.

[14] [Execute] 를 누릅니다.

[15] 모든 과정이 완료되면 [Finish]를 누릅니다.

[16] Next를 누릅니다.

[17] 이제 정말로 설치가 완료됐습니다! MySQL 이 제대로 설치됐는지 확인합니다.


 

+ Recent posts