https://www.acmicpc.net/problem/5547

 

5547번: 일루미네이션

첫째 줄에 두 개의 정수 W와 H가 주어진다. (1 ≤ W, H ≤ 100) 다음 H줄에는 상근이네 집의 건물 배치가 주어진다. i+1줄에는 W개의 정수가 공백으로 구분되어 있다. j번째 (1 ≤ j ≤ w) 정수의 좌표는

www.acmicpc.net

 

위 그림의 좌표와 상관없이 저는 (1, 1) ~ (N, M)으로 입력을 받았습니다.

나중에 x의 좌표에 따라 인접하는 좌표들만 구분하면 되는 것입니다.

 

이 문제의 핵심은 건물 외부 체크를 어떻게 하느냐입니다.

왼쪽 건물들을 보시면 내부에도 흰색이 존재합니다. 이거를 잘 걸러내야 합니다.

 

저는 배열의 크기를 (N + 2, M + 2)로 설계하였고,

(1, 1) ~ (N, M)에 건물 정도를 입력 받아 가장자리에 있는 좌표에는 모두 건물 외부가 올 수 있게끔 하였습니다.

(0, 0)이나 (N + 1, M + 1)에 있는 것은 무조건 건물 외부 (흰색) 입니다.

그러면 무조건 흰색이 되는 (0, 0)을 시작으로 bfs를 돌려 건물 외부들을 모두 체크할 수있습니다.

 

이후 건물을 bfs로 순회하여 각 좌표에서 인접한 건물이 몇 개 있는지 세어 줍니다.

이 때, 건물 외부의 흰색은 카운팅을 하지 않으며, 건물 내부의 흰색은 카운팅을 합니다.

그래야 건물 내부에도 조명을 설치하지 않습니다. [위 사진 기준 (2, 3)이 예시입니다.]

 

카운팅이 완료되었으면 해당 좌표에서 조명을 설치할 벽면의 길이를 구합니다.

벽면의 길이는 인접한 건물이 0개 ~ 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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <iostream>
#include <algorithm>
#include <queue>
#define MAX 103
#define LEN 6
using namespace std;
typedef pair<intint> pi;
 
int list[MAX][MAX];
bool visit[MAX][MAX], sideChk[MAX][MAX];
int direct[2][6][2= {
    {{-1,-1},{-1,0},{0,1},{1,0},{1,-1},{0,-1}},
    {{0,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0}}
};
int len[7];
int N, M, ans;
 
void sideBfs(int sx, int sy) {
    queue<pi> q;
    q.push({ sx,sy });
    sideChk[sx][sy] = true;
    while (!q.empty()) {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
 
        int idx = x % 2;
        for (int d = 0; d < 6; d++) {
            int nx = x + direct[idx][d][0];
            int ny = y + direct[idx][d][1];
 
            if (nx < 0 || ny < 0 || nx > N + 1 || ny > M + 1continue;
            if (list[nx][ny] || sideChk[nx][ny]) continue;
 
            q.push({ nx,ny });
            sideChk[nx][ny] = true;
        }
    }
}
 
void bfs(int sx, int sy) {
    queue<pi> q;
    q.push({ sx,sy });
    visit[sx][sy] = true;
    while (!q.empty()) {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
 
        int cnt = 0;
        int idx = x % 2;
        for (int d = 0; d < 6; d++) {
            int nx = x + direct[idx][d][0];
            int ny = y + direct[idx][d][1];
 
            if (nx <= 0 || ny <= 0 || nx > N + 1 || ny > M + 1continue;
            if (!list[nx][ny]) {
                if (!sideChk[nx][ny]) cnt++;
                continue;
            }
            cnt++;
            if (visit[nx][ny]) continue;
 
            q.push({ nx,ny });
            visit[nx][ny] = true;
        }
 
        ans += len[cnt];
    }
}
 
void func() {
    sideBfs(00);
 
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            if (!list[i][j] || visit[i][j]) continue;
 
            bfs(i, j);
        }
    }
 
    cout << ans << '\n';
}
 
void init() {
    for (int i = 0; i <= LEN; i++) {
        len[i] = LEN - i;
    }
}
 
void input() {
    cin >> M >> N;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            cin >> list[i][j];
        }
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    init();
    input();
    func();
 
    return 0;
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 18112 이진수 게임  (0) 2022.09.16
boj 16946 벽 부수고 이동하기 4  (0) 2022.05.22
boj 16932 모양 만들기  (0) 2022.05.14
boj 17244 아맞다우산  (0) 2021.11.25
boj 1194 달이 차오른다, 가자.  (0) 2021.04.21

https://www.acmicpc.net/problem/16932

 

16932번: 모양 만들기

N×M인 배열에서 모양을 찾으려고 한다. 배열의 각 칸에는 0과 1 중의 하나가 들어있다. 두 칸이 서로 변을 공유할때, 두 칸을 인접하다고 한다. 1이 들어 있는 인접한 칸끼리 연결했을 때, 각각의

www.acmicpc.net

정말 오랜만에 알고리즘 포스팅입니다.

 

이 문제는 배열의 값이 0인 한 칸을 1로 변경하여 만들 수 있는 모양의 최대 크기를 구하는 문제입니다.

이 문제에서 모양이란 배열 내에서 1로 이루어진 연결 요소입니다.

 

저는 bfs를 통해 1로 이루어진 모양들을 넘버링하여 해당 넘버링의 크기를 vector에 넣어주었고,

브루트포스를 통해 값이 0인 칸들의 인접한 칸들의 크기 합을 구해 max를 구하였습니다.

이 때, 인접한 칸에서 같은 넘버링이 나올 수 있으므로 중복체크를 위해 set을 사용하였습니다.

 

넘버링했다는 것은

0 1 1
0 0 1
0 1 0

이렇게 되어있는 배열을

0 1 1
0 0 1
0 2 0

이렇게 모양별로 구분할 수 있도록 변경하였습니다.

이 상태에서 브루트포스로 모양들을 연결해주는 것입니다.

 

여기서 인접한 칸에서 같은 넘버링이 나오는 경우는 좌표 (1, 1)을 보시면 이해하실 수 있습니다.

0 1 1
0 0 1
0 2 0
(1, 1)을 1로 변경한다고 했을 때 위(0, 1)와 오른쪽(1, 2)은 같은 넘버링을 가진 모양입니다.
이미 같은 모양에 속하므로 이를 중복으로 더해서는 안됩니다.
따라서 중복체크를 위해 set을 사용하였습니다.

 

 

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <iostream>
#include <queue>
#include <vector>
#include <set>
#define MAX 1001
using namespace std;
typedef pair<intint> pi;
 
int list[MAX][MAX];
bool visit[MAX][MAX];
int direct[4][2= { {0,1},{1,0},{0,-1},{-1,0} };
vector<int> sizeList;
int N, M;
 
void bfs(int sx, int sy, int num) {
    int ret = 0;
    queue<pi> q;
    q.push({ sx,sy });
    visit[sx][sy] = true;
    while (!q.empty()) {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
 
        ret++;
        list[x][y] = num;
 
        for (int i = 0; i < 4; i++) {
            int nx = x + direct[i][0];
            int ny = y + direct[i][1];
 
            if (nx < 0 || ny < 0 || nx >= N || ny >= M) continue;
            if (!list[nx][ny] || visit[nx][ny]) continue;
 
            q.push({ nx,ny });
            visit[nx][ny] = true;
        }
    }
 
    sizeList.push_back(ret);
}
 
void func() {
    sizeList.push_back(0);
    int num = 1;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (!list[i][j] || visit[i][j]) continue;
 
            bfs(i, j, num++);
        }
    }
 
    int ans = 0;
    set<int> s;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (list[i][j]) continue;
 
            int ret = 0;
            for (int d = 0; d < 4; d++) {
                int nx = i + direct[d][0];
                int ny = j + direct[d][1];
 
                if (nx < 0 || ny < 0 || nx >= N || ny >= M) continue;
                if (!list[nx][ny]) continue;
                if (s.find(list[nx][ny]) != s.end()) continue;
 
                s.insert(list[nx][ny]);
                ret += sizeList[list[nx][ny]];
            }
 
            ans = max(ans, ret + 1);
            s.clear();
        }
    }
 
    cout << ans << '\n';
}
 
void input() {
    cin >> N >> M;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> list[i][j];
        }
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
 
    return 0;
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 16946 벽 부수고 이동하기 4  (0) 2022.05.22
boj 5547 일루미네이션  (0) 2022.05.15
boj 17244 아맞다우산  (0) 2021.11.25
boj 1194 달이 차오른다, 가자.  (0) 2021.04.21
boj 17471 게리맨더링  (0) 2021.04.16

https://www.acmicpc.net/problem/17244

 

17244번: 아맞다우산

경재씨는 저녁 약속을 가기 전 챙기지 않은 물건들이 있는 지 확인하고 있다. 필요한 물건은 전부 챙긴 것 같았고 외출 후 돌아오는 길에 경재씨는 외쳤다. "아 맞다 우산!!!" 경재 씨는 매번 외출

www.acmicpc.net

챙겨야 하는 물건은 최대 5개이므로 bfs + 비트마스킹이 가능합니다.

visit[x][y][bit]: 좌표 (x, y)에 도착했을 때 찾은 물건의 비트가 bit인 경우의 방문 처리입니다.

비트를 어떻게 할지 고민하다가 chk배열을 사용하여 해당 좌표에 있는 물건의 비트를 정해주었습니다.

나가는 문에 도착했을 때 모든 물건을 찾았을 때만 t를 출력합니다.

 

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>
#define MAX 50
using namespace std;
typedef pair<pair<intint>int> pii;
 
queue<pii> q;
char list[MAX][MAX];
bool visit[MAX][MAX][1 << 5];
int chk[MAX][MAX];
int direct[4][2= { {0,1},{1,0},{0,-1},{-1,0} };
int N, M, bit;
 
void bfs() {
    for (int t = 1!q.empty(); t++) {
        int qsize = q.size();
        while (qsize--) {
            int x = q.front().first.first;
            int y = q.front().first.second;
            int cnt = q.front().second;
            q.pop();
 
            for (int i = 0; i < 4; i++) {
                int nx = x + direct[i][0];
                int ny = y + direct[i][1];
                int ncnt = cnt;
 
                if (nx < 0 || ny < 0 || nx >= N || ny >= M) continue;
                if (list[nx][ny] == 'X') {
                    int b = chk[nx][ny];
 
                    ncnt |= b;
                }
                if (list[nx][ny] == '#' || visit[nx][ny][ncnt]) continue;
 
                if (list[nx][ny] == 'E' && ncnt == bit) {
                    cout << t << '\n';
                    return;
                }
 
                q.push({ {nx,ny}, ncnt });
                visit[nx][ny][ncnt] = true;
            }
        }
    }
}
 
void input() {
    int cnt = 0;
    cin >> M >> N;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> list[i][j];
            if (list[i][j] == 'S') {
                q.push({ {i,j},0 });
                visit[i][j][0= true;
            }
            else if (list[i][j] == 'X') {
                chk[i][j] = (1 << cnt);
                cnt++;
            }
        }
    }
 
    bit = (1 << cnt) - 1;
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    bfs();
 
    return 0;
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 5547 일루미네이션  (0) 2022.05.15
boj 16932 모양 만들기  (0) 2022.05.14
boj 1194 달이 차오른다, 가자.  (0) 2021.04.21
boj 17471 게리맨더링  (0) 2021.04.16
boj 2573 빙산  (0) 2021.04.05

www.acmicpc.net/problem/1194

 

1194번: 달이 차오른다, 가자.

첫째 줄에 미로의 세로 크기 N과 가로 크기 M이 주어진다. (1 ≤ N, M ≤ 50) 둘째 줄부터 N개의 줄에 미로의 모양이 주어진다. 같은 타입의 열쇠가 여러 개 있을 수 있고, 문도 마찬가지이다. 그리고,

www.acmicpc.net

기본적인 bfs에 비트마스킹이 더해진 문제입니다.

 

visit[x][y][key] : (x, y)에 도달했을 때 갖고있는 열쇠 종류

문을 열기 위해서는 열쇠를 갖고있어야 하므로 얻은 열쇠를 비트마스킹을 이용하여 관리합니다.

 

로직은 다른 bfs와 똑같이 돌아가며, 확인해야할 조건은

1. 맵 밖으로 나갈 경우

2. 문을 만났을 경우

3. 열쇠를 만났을 경우

4. 해당 좌표를 이미 방문한 경우

5. 벽을 만난 경우

 

1, 4, 5인 경우에는 continue를 해주시면 되고,

2인 경우에는 열쇠가 없는 경우에만 continue를 해주시면 됩니다.

3인 경우에는 열쇠를 추가합니다.

 

탈출에 성공하였으면 현재 시간을 출력해주시고, 큐가 비었는데도 탈출하지 못했으면 -1을 출력합니다.

 

 

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Deque<int[]> dq = new ArrayDeque<>();
    static char list[][] = new char[51][51];
    static boolean visit[][][] = new boolean[51][51][64];
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static int N, M;
 
    static void bfs() {
        for (int t = 0!dq.isEmpty(); t++) {
            int size = dq.size();
            while (size-- > 0) {
                int x = dq.peek()[0];
                int y = dq.peek()[1];
                int key = dq.poll()[2];
 
                if (list[x][y] == '1') {
                    System.out.println(t);
                    return;
                }
                for (int i = 0; i < 4; i++) {
                    int nx = x + direct[i][0];
                    int ny = y + direct[i][1];
                    int nextKey = key;
 
                    if (nx < 0 || ny < 0 || nx >= N || ny >= M)
                        continue;
                    if ('A' <= list[nx][ny] && list[nx][ny] <= 'F') {
                        int door = list[nx][ny] - 'A';
 
                        if ((key & (1 << door)) == 0)
                            continue;
                    }
                    if ('a' <= list[nx][ny] && list[nx][ny] <= 'f') {
                        nextKey = nextKey | (1 << (list[nx][ny] - 'a'));
                    }
 
                    if (visit[nx][ny][nextKey] || list[nx][ny] == '#')
                        continue;
                    dq.add(new int[] { nx, ny, nextKey });
                    visit[nx][ny][nextKey] = true;
                }
            }
        }
        
        System.out.println(-1);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            list[i] = st.nextToken().toCharArray();
            for (int j = 0; j < M; j++) {
                if (list[i][j] == '0') {
                    dq.add(new int[] { i, j, 0 });
                    visit[i][j][0= true;
                }
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        bfs();
    }
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 16932 모양 만들기  (0) 2022.05.14
boj 17244 아맞다우산  (0) 2021.11.25
boj 17471 게리맨더링  (0) 2021.04.16
boj 2573 빙산  (0) 2021.04.05
boj 14923 미로 탈출  (0) 2021.03.29

www.acmicpc.net/problem/17471

 

17471번: 게리맨더링

선거구를 [1, 4], [2, 3, 5, 6]으로 나누면 각 선거구의 인구는 9, 8이 된다. 인구 차이는 1이고, 이 값보다 더 작은 값으로 선거구를 나눌 수는 없다.

www.acmicpc.net

선거구를 두 구간으로 나누는데 나눠진 구간끼리 연결되어 있어야합니다.

 

dfs기반의 부분집합으로 나눌 수 있는 모든 구간을 확인합니다.

두 구간을 div1, div2라는 리스트를 사용하였고, 구역들끼리 연결되어있는지 bfs를 통해 확인합니다.

구간의 모든 구역끼리 연결되어 있으면 구역들의 합의 최솟값을 갱신합니다.

두 선거구로 나눌 수 없는 경우가 입력으로 주어질 수 있으니 그 때는 -1을 출력합니다.

 

 

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.StringTokenizer;
 
public class Main {
    static ArrayList<Integer> graph[] = new ArrayList[11];
    static ArrayList<Integer> div1 = new ArrayList<>();
    static ArrayList<Integer> div2 = new ArrayList<>();
    static int list[] = new int[11];
    static boolean pick[] = new boolean[11];
    static boolean visit[] = new boolean[11];
    static int N, ans = 2147483647;
 
    static boolean bfs(ArrayList<Integer> div, int size, boolean t) {
        Arrays.fill(visit, false);
        Deque<Integer> dq = new ArrayDeque<>();
        dq.add(div.get(0));
        visit[div.get(0)] = true;
        int cnt = 0;
        while (!dq.isEmpty()) {
            int x = dq.poll();
            cnt++;
            for (int i = 0; i < graph[x].size(); i++) {
                int next = graph[x].get(i);
 
                if (visit[next] || pick[next] != t)
                    continue;
 
                visit[next] = true;
                dq.add(next);
            }
        }
 
        if (cnt == size)
            return true;
        else
            return false;
    }
 
    static void func(int idx) {
        if (!div1.isEmpty()) {
            for (int i = 1; i <= N; i++) {
                if (!pick[i])
                    div2.add(i);
            }
            
            if(!div2.isEmpty()) {
                if (bfs(div1, div1.size(), true)) {
                    if (bfs(div2, div2.size(), false)) {
                        int sum = 0;
                        for (int i = 0; i < div1.size(); i++) {
                            sum += list[div1.get(i)];
                        }
 
                        for (int i = 0; i < div2.size(); i++) {
                            sum -= list[div2.get(i)];
                        }
 
                        ans = Math.min(ans, Math.abs(sum));
                    }
                }
                div2.clear();
            }
        }
 
        for (int i = idx; i <= N; i++) {
            div1.add(i);
            pick[i] = true;
            func(i + 1);
            pick[i] = false;
            div1.remove(div1.size() - 1);
        }
    }
 
    static void input() throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
 
        st = new StringTokenizer(br.readLine());
        for (int i = 1; i <= N; i++) {
            list[i] = Integer.parseInt(st.nextToken());
        }
 
        int K, v;
        for (int i = 1; i <= N; i++) {
            st = new StringTokenizer(br.readLine());
            K = Integer.parseInt(st.nextToken());
            graph[i] = new ArrayList<>();
            while (K-- > 0) {
                v = Integer.parseInt(st.nextToken());
                graph[i].add(v);
            }
        }
    }
 
    static void print() {
        if (ans == 2147483647)
            System.out.println(-1);
        else
            System.out.println(ans);
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func(1);
        print();
    }
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 17244 아맞다우산  (0) 2021.11.25
boj 1194 달이 차오른다, 가자.  (0) 2021.04.21
boj 2573 빙산  (0) 2021.04.05
boj 14923 미로 탈출  (0) 2021.03.29
boj 17836 공주님을 구해라!  (0) 2021.03.26

www.acmicpc.net/problem/2573

 

2573번: 빙산

첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을

www.acmicpc.net

먼저 빙산 주위에 바다가 있는 위치 수만큼 빙산이 녹습니다.

 

이중for문으로 이거를 확인해주시면 되고, 주위에 바다가 있을 때마다 cnt[i][j]를 1씩 늘려줍니다.

그 다음 이중for문을 다시 돌려서 cnt[i][j]만큼 빙산을 녹여줍니다.

 

빙산을 녹이는 과정에서 빙산이 두 덩어리 이상으로 분리가 되면 그 시간을 출력해주시면 됩니다.

이 과정을 bfs로 구현하였습니다. 이중for문을 돌면서 방문안된 빙산을 발견하면 bfs를 호출하는데

만약 두 번째로 bfs에 들어가게 되면 빙산이 분리가 되었다는 말이 되기때문에 바로 시간을 출력해주시면 됩니다.

 

저는 문제를 읽어보니 최초로 주어지는 입력에는 무조건 빙산이 한 덩어리라는 조건이 없어서

빙산이 두 덩어리 이상으로 분리가 되었는지 체크하는 bfs함수를 먼저 호출하였습니다.

 

 

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int list[][] = new int[300][300];
    static int cnt[][] = new int[300][300];
    static boolean visit[][] = new boolean[300][300];
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static int N, M;
 
    static void init() {
        for (int i = 0; i < N; i++)
            Arrays.fill(visit[i], false);
    }
 
    static void bfs(int sx, int sy) {
        Deque<int[]> dq = new ArrayDeque<>();
        dq.add(new int[] { sx, sy });
        visit[sx][sy] = true;
        while (!dq.isEmpty()) {
            int x = dq.peek()[0];
            int y = dq.poll()[1];
 
            for (int i = 0; i < 4; i++) {
                int nx = x + direct[i][0];
                int ny = y + direct[i][1];
 
                if (visit[nx][ny] || list[nx][ny] == 0)
                    continue;
 
                dq.add(new int[] { nx, ny });
                visit[nx][ny] = true;
            }
        }
    }
 
    static void func() {
        for (int t = 0;; t++) {
            boolean chk = false;
 
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    if (list[i][j] == 0 || visit[i][j])
                        continue;
                    if (chk) {
                        System.out.println(t);
                        return;
                    }
                    bfs(i, j);
                    chk = true;
                }
            }
 
            if (!chk) {
                System.out.println(0);
                return;
            }
 
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    if (list[i][j] == 0)
                        continue;
                    for (int k = 0; k < 4; k++) {
                        int nx = i + direct[k][0];
                        int ny = j + direct[k][1];
 
                        if (list[nx][ny] == 0)
                            cnt[i][j]++;
                    }
                }
            }
 
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    if (list[i][j] == 0)
                        continue;
                    list[i][j] = list[i][j] >= cnt[i][j] ? list[i][j] - cnt[i][j] : 0;
                    cnt[i][j] = 0;
                }
            }
            
            init();
        }
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                list[i][j] = Integer.parseInt(st.nextToken());
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 1194 달이 차오른다, 가자.  (0) 2021.04.21
boj 17471 게리맨더링  (0) 2021.04.16
boj 14923 미로 탈출  (0) 2021.03.29
boj 17836 공주님을 구해라!  (0) 2021.03.26
boj 9205 맥주 마시면서 걸어가기  (0) 2021.03.25

www.acmicpc.net/problem/14923

 

14923번: 미로 탈출

홍익이는 사악한 마법사의 꾐에 속아 N x M 미로 (Hx, Hy) 위치에 떨어졌다. 다행히도 홍익이는 마법사가 만든 미로의 탈출 위치(Ex, Ey)를 알고 있다. 하지만 미로에는 곳곳에 마법사가 설치한 벽이

www.acmicpc.net

(hx, hy)에서 출발하여 (ex, ey)까지 갈 수 있는 최단거리를 출력합니다.

맵에는 벽이 있으며 벽을 1개까지 부술 수 있습니다.

 

www.acmicpc.net/problem/2206

 

2206번: 벽 부수고 이동하기

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로

www.acmicpc.net

이 문제와 같은 풀이방식입니다.

이 문제와 다른점은 출발점과 도착점이 고정이 아니라는 점입니다.

 

visit[x][y][cnt] : (x, y)에 벽을 부수고 방문한 경우와 안부수고 방문한 경우를 나눠줍니다.

 

탈출이 가능하면 거리를 출력, 불가능하면 -1을 출력합니다.

 

 

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
77
78
79
80
81
82
83
84
85
86
87
88
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Deque<int[]> dq = new ArrayDeque<>();
    static int list[][] = new int[1001][1001];
    static boolean visit[][][] = new boolean[1001][1001][2];
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static int N, M, ex, ey;
 
    static void bfs() {
        for (int t = 1;; t++) {
            int size = dq.size();
            while (size-- > 0) {
                int x = dq.peek()[0];
                int y = dq.peek()[1];
                int cnt = dq.poll()[2];
 
                for (int i = 0; i < 4; i++) {
                    int nx = x + direct[i][0];
                    int ny = y + direct[i][1];
 
                    if (nx < 1 || ny < 1 || nx > N || ny > M)
                        continue;
                    if (list[nx][ny] == 1) {
                        if (cnt > 0 || visit[nx][ny][1])
                            continue;
 
                        dq.add(new int[] { nx, ny, 1 });
                        visit[nx][ny][1= true;
                    } else {
                        if (visit[nx][ny][cnt])
                            continue;
 
                        dq.add(new int[] { nx, ny, cnt });
                        visit[nx][ny][cnt] = true;
 
                        if (nx == ex && ny == ey) {
                            System.out.println(t);
                            return;
                        }
                    }
                }
            }
 
            if (dq.isEmpty()) {
                System.out.println(-1);
                return;
            }
        }
    }
 
    static void input() throws Exception {
        int x, y;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
 
        st = new StringTokenizer(br.readLine());
        x = Integer.parseInt(st.nextToken());
        y = Integer.parseInt(st.nextToken());
        dq.add(new int[] { x, y, 0 });
        visit[x][y][0= true;
 
        st = new StringTokenizer(br.readLine());
        x = Integer.parseInt(st.nextToken());
        y = Integer.parseInt(st.nextToken());
        ex = x;
        ey = y;
 
        for (int i = 1; i <= N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 1; j <= M; j++) {
                list[i][j] = Integer.parseInt(st.nextToken());
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        bfs();
    }
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 17471 게리맨더링  (0) 2021.04.16
boj 2573 빙산  (0) 2021.04.05
boj 17836 공주님을 구해라!  (0) 2021.03.26
boj 9205 맥주 마시면서 걸어가기  (0) 2021.03.25
boj 1600 말이 되고픈 원숭이  (0) 2021.03.24

www.acmicpc.net/problem/17836

 

17836번: 공주님을 구해라!

용사는 마왕이 숨겨놓은 공주님을 구하기 위해 (N, M) 크기의 성 입구 (1,1)으로 들어왔다. 마왕은 용사가 공주를 찾지 못하도록 성의 여러 군데 마법 벽을 세워놓았다. 용사는 현재의 가지고 있는

www.acmicpc.net

시작점 : (1, 1)

도착점 : (N, M)

제한 시간 : T

무기가 없으면 벽을 지나갈 수 없지만 무기가 있으면 모든 벽을 부수고 지나갈 수 있습니다.


visit[x][y][chk] : x, y에 도달했을 때 무기를 가진 상태로 방문했는지 여부

 

1. 다음 칸이 무기가 있는 칸일 경우(list[nx][ny] = 2)

- 무기를 획득하였으므로 chk=true인 값을 큐에 넣어줍니다.

2. 다음 칸이 벽이 아니고 방문하지 않았을 경우

- 평상시 bfs처럼 다음 정점을 큐에 넣고 방문체크합니다.

3. 다음 칸이 벽이고 무기를 가진 상태인 경우

- 무기를 갖고있으면 어디든 지나갈 수 있으므로 2번과 같은 로직을 수행합니다.

 

도착지점인 (N, M)의 값은 0이므로 2, 3번에서 (N, M)에 도달하였으면 현재 시간을 출력합니다.

만약 T시간 동안 (N, M)에 도달하지 못하면 Fail을 출력합니다.

 

 

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
77
#include <iostream>
#include <queue>
using namespace std;
 
typedef struct Point {
    int x;
    int y;
    bool chk;
};
 
queue<Point> q;
bool visit[101][101][2];
int list[101][101];
int direct[4][2= { {0,1},{1,0},{0,-1},{-1,0} };
int N, M, T;
 
void bfs() {
    q.push({ 1,1,false });
    visit[1][1][0= true;
    for (int t = 1; t <= T; t++) {
        int qsize = q.size();
        while (qsize--) {
            int x = q.front().x;
            int y = q.front().y;
            bool chk = q.front().chk;
            q.pop();
 
            for (int i = 0; i < 4; i++) {
                int nx = x + direct[i][0];
                int ny = y + direct[i][1];
 
                if (nx < 1 || ny < 1 || nx > N || ny > M) continue;
                if (list[nx][ny] == 2 && !visit[nx][ny][1]) {
                    q.push({ nx,ny,true });
                    visit[nx][ny][1= true;
                }
                else if (list[nx][ny] == 0 && !visit[nx][ny][chk]) {
                    q.push({ nx,ny,chk });
                    visit[nx][ny][chk] = true;
                    if (nx == N && ny == M) {
                        cout << t << '\n';
                        return;
                    }
                }
                else if (list[nx][ny] == 1 && chk && !visit[nx][ny][chk]) {
                    q.push({ nx,ny,chk });
                    visit[nx][ny][chk] = true;
                    if (nx == N && ny == M) {
                        cout << t << '\n';
                        return;
                    }
                }
            }
        }
    }
 
    cout << "Fail\n";
}
 
void input() {
    cin >> N >> M >> T;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            cin >> list[i][j];
        }
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    bfs();
 
    return 0;
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 2573 빙산  (0) 2021.04.05
boj 14923 미로 탈출  (0) 2021.03.29
boj 9205 맥주 마시면서 걸어가기  (0) 2021.03.25
boj 1600 말이 되고픈 원숭이  (0) 2021.03.24
boj 2589 보물섬  (0) 2021.03.16

www.acmicpc.net/problem/9205

 

9205번: 맥주 마시면서 걸어가기

송도에 사는 상근이와 친구들은 송도에서 열리는 펜타포트 락 페스티벌에 가려고 한다. 올해는 맥주를 마시면서 걸어가기로 했다. 출발은 상근이네 집에서 하고, 맥주 한 박스를 들고 출발한다.

www.acmicpc.net

1번 정점 : 시작점

2번 ~ N + 1번 정점 : 편의점

N + 2번 정점 : 도착점

 

bfs와 플로이드 와샬 두 가지 방법을 이용할 수 있습니다.

 

먼저 bfs 풀이로는 N^2으로 각 정점들 사이의 거리가 1000이하인 간선만 그래프화 시켜줍니다.

그 다음 1번정점으로 시작하여 bfs로 인접한 모든 정점을 방문한 후에 N + 2번 정점을 방문하였는지 확인합니다.

N + 2번 정점을 방문 하였으면 happy, 방문 안했으면 sad를 출력합니다.

 

 

플로이드 풀이로는 N^2으로 각 정점들 사이의 거리가 1000이하면 dis[i][j] = true를 하여 간선체크를 해줍니다.

그 다음 플로이드를 사용하는데 i ~ k번을 지나갈 수 있고, k ~ j번을 지나갈 수 있으면 i ~ j번을 지나갈 수 있습니다.

따라서 dis[i][k] && dis[k][j]이면 dis[i][j] = true를 해줍니다.

dis[1][N+2] = true면 happy, false면 sad를 출력합니다.

 

bfs
플로이드 와샬

 

실행 시간은 bfs쪽이 좀 더 빨랐습니다.

 

 

[bfs]

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
77
78
79
80
81
82
83
84
85
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static ArrayList<Integer> graph[] = new ArrayList[103];
    static boolean visit[] = new boolean[103];
    static int list[][] = new int[103][2];
    static int N;
 
    static void bfs() {
        Deque<Integer> dq = new ArrayDeque<>();
        dq.add(1);
        visit[1= true;
        while (!dq.isEmpty()) {
            int x = dq.poll();
 
            for (int i = 0; i < graph[x].size(); i++) {
                int next = graph[x].get(i);
 
                if (visit[next])
                    continue;
 
                dq.add(next);
                visit[next] = true;
            }
        }
 
        if (visit[N + 2])
            sb.append("happy\n");
        else
            sb.append("sad\n");
    }
 
    static boolean getDis(int a[], int b[]) {
        return (Math.abs(a[0- b[0]) + Math.abs(a[1- b[1])) <= 1000 ? true : false;
    }
 
    static void func() {
        for (int i = 1; i <= N + 1; i++) {
            for (int j = i + 1; j <= N + 2; j++) {
                if (getDis(list[i], list[j])) {
                    graph[i].add(j);
                    graph[j].add(i);
                }
            }
        }
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        for (int i = 1; i <= N + 2; i++) {
            st = new StringTokenizer(br.readLine());
            list[i][0= Integer.parseInt(st.nextToken());
            list[i][1= Integer.parseInt(st.nextToken());
        }
    }
 
    static void init() {
        Arrays.fill(visit, false);
        for (int i = 1; i <= N + 2; i++) {
            graph[i] = new ArrayList<>();
        }
    }
 
    public static void main(String[] args) throws Exception {
        st = new StringTokenizer(br.readLine());
        int tc = Integer.parseInt(st.nextToken());
        while (tc-- > 0) {
            input();
            init();
            func();
            bfs();
        }
        System.out.println(sb.toString());
    }
}
cs

 

 

[플로이드 와샬]

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static StringBuffer sb = new StringBuffer();
    static int list[][] = new int[103][2];
    static boolean dis[][] = new boolean[103][103];
    static int N;
 
    static int getDis(int x, int y, int tx, int ty) {
        return Math.abs(x - tx) + Math.abs(y - ty);
    }
 
    static void func() {
        for (int i = 1; i <= N + 1; i++) {
            for (int j = i + 1; j <= N + 2; j++) {
                if (getDis(list[i][0], list[i][1], list[j][0], list[j][1]) <= 1000) {
                    dis[i][j] = true;
                    dis[j][i] = true;
                }
            }
        }
 
        for (int k = 1; k <= N + 2; k++) {
            for (int i = 1; i <= N + 2; i++) {
                for (int j = 1; j <= N + 2; j++) {
                    if (dis[i][k] && dis[k][j])
                        dis[i][j] = true;
                }
            }
        }
 
        if (dis[1][N + 2])
            sb.append("happy\n");
        else
            sb.append("sad\n");
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        for (int i = 1; i <= N + 2; i++) {
            st = new StringTokenizer(br.readLine());
            list[i][0= Integer.parseInt(st.nextToken());
            list[i][1= Integer.parseInt(st.nextToken());
        }
    }
 
    static void init() {
        for (int i = 1; i <= N + 2; i++)
            Arrays.fill(dis[i], false);
    }
 
    public static void main(String[] args) throws Exception {
        st = new StringTokenizer(br.readLine());
        int tc = Integer.parseInt(st.nextToken());
        for (int t = 1; t <= tc; t++) {
            input();
            func();
            init();
        }
 
        System.out.println(sb.toString());
    }
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 14923 미로 탈출  (0) 2021.03.29
boj 17836 공주님을 구해라!  (0) 2021.03.26
boj 1600 말이 되고픈 원숭이  (0) 2021.03.24
boj 2589 보물섬  (0) 2021.03.16
boj 11559 Puyo Puyo  (0) 2021.02.26

www.acmicpc.net/problem/1600

 

1600번: 말이 되고픈 원숭이

첫째 줄에 정수 K가 주어진다. 둘째 줄에 격자판의 가로길이 W, 세로길이 H가 주어진다. 그 다음 H줄에 걸쳐 W개의 숫자가 주어지는데, 0은 아무것도 없는 평지, 1은 장애물을 뜻한다. 장애물이 있

www.acmicpc.net

bfs 탐색인데 4방탐색에 위 사진과 같은 이동방식이 추가되었습니다.

위 사진처럼 말과 같이 움직일 수 있는 횟수가 K로 정해져있습니다. (0 <= K <= 30)

 

그러므로 방문체크는 3차원 배열로 해줍니다.

visit[x][y][k] : 말과 같이 움직인 횟수가 k번인 상태로 (x, y)에 도착한 경우

 

저는 방향탐색에 대한 좌표이동을 인덱스를 기준으로 나누었습니다.

1. 0 ~ 3번 인덱스 : 4방탐색

2. 4 ~ 11번 인덱스 : 말처럼 이동

4방탐색의 경우 k의 변화 없이 이동시켜줍니다.

말처럼 이동하는 경우 K미만으로 움직였을 경우에만 움직여줍니다.

 

(N - 1, M - 1)에 도달하였으면 시간을 출력합니다.

 

 

[C++]

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
#include <iostream>
#include <queue>
using namespace std;
 
queue<pair<pair<intint>pair<intint> > > q;
bool visit[200][200][31];
int map[200][200];
int x_direct[] = { 0,1,0,-1,-2,-1,1,2,2,1,-1,-2 }, y_direct[] = { 1,0,-1,0,1,2,2,1,-1,-2,-2,-1 };
int K, H, W, ans = -1;
 
void bfs() {
    while (!q.empty()) {
        int x = q.front().first.first;
        int y = q.front().first.second;
        int cnt = q.front().second.first;
        int horse = q.front().second.second;
        q.pop();
 
        if (x == H - 1 && y == W - 1) {
            ans = cnt;
            return;
        }
 
        for (int i = 0; i < 12; i++) {
            int xx = x + x_direct[i];
            int yy = y + y_direct[i];
 
            if (xx < 0 || yy < 0 || xx >= H || yy >= W) continue;
            if (map[xx][yy] == 1continue;
 
            if (x_direct[i] == 2 || x_direct[i] == -2 || y_direct[i] == 2 || y_direct[i] == -2) {
                if (visit[xx][yy][horse + 1|| horse == K) continue;
                q.push(make_pair(make_pair(xx, yy), make_pair(cnt + 1, horse + 1)));
                visit[xx][yy][horse + 1= true;
            }
            else {
                if (visit[xx][yy][horse]) continue;
                q.push(make_pair(make_pair(xx, yy), make_pair(cnt + 1, horse)));
                visit[xx][yy][horse] = true;
            }
        }
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    cin >> K >> W >> H;
    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            cin >> map[i][j];
        }
    }
 
    q.push(make_pair(make_pair(00), make_pair(00)));
    visit[0][0][0= true;
    bfs();
 
    cout << ans << '\n';
 
    return 0;
}
cs

 

 

[Java]

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
77
78
79
80
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int list[][] = new int[201][201];
    static boolean visit[][][] = new boolean[201][201][31];
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 }, { 12 }, { 1-2 }, { -12 }, { -1-2 },
            { 21 }, { 2-1 }, { -21 }, { -2-1 } };
    static int N, M, K;
 
    static void bfs() {
        Deque<int[]> dq = new ArrayDeque<>();
        dq.add(new int[] { 000 });
        visit[0][0][0= true;
        for (int t = 1;; t++) {
            int size = dq.size();
            while (size-- > 0) {
                int x = dq.peek()[0];
                int y = dq.peek()[1];
                int cnt = dq.poll()[2];
 
                if (x == N - 1 && y == M - 1) {
                    System.out.println(t - 1);
                    return;
                }
 
                for (int i = 0; i < 12; i++) {
                    int nx = x + direct[i][0];
                    int ny = y + direct[i][1];
 
                    if (nx < 0 || ny < 0 || nx >= N || ny >= M)
                        continue;
                    if (list[nx][ny] == 1)
                        continue;
 
                    if (i < 4) {
                        if (visit[nx][ny][cnt])
                            continue;
                        dq.add(new int[] { nx, ny, cnt });
                        visit[nx][ny][cnt] = true;
                    } else {
                        if (cnt + 1 > K || visit[nx][ny][cnt + 1])
                            continue;
                        dq.add(new int[] { nx, ny, cnt + 1 });
                        visit[nx][ny][cnt + 1= true;
                    }
                }
            }
 
            if (dq.isEmpty()) {
                System.out.println(-1);
                return;
            }
        }
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        K = Integer.parseInt(st.nextToken());
        st = new StringTokenizer(br.readLine());
        M = Integer.parseInt(st.nextToken());
        N = Integer.parseInt(st.nextToken());
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                list[i][j] = Integer.parseInt(st.nextToken());
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        bfs();
    }
}
cs

'algorithm > bfs' 카테고리의 다른 글

boj 17836 공주님을 구해라!  (0) 2021.03.26
boj 9205 맥주 마시면서 걸어가기  (0) 2021.03.25
boj 2589 보물섬  (0) 2021.03.16
boj 11559 Puyo Puyo  (0) 2021.02.26
boj 15653 구슬 탈출 4  (0) 2021.02.22

www.acmicpc.net/problem/18352

 

18352번: 특정 거리의 도시 찾기

첫째 줄에 도시의 개수 N, 도로의 개수 M, 거리 정보 K, 출발 도시의 번호 X가 주어진다. (2 ≤ N ≤ 300,000, 1 ≤ M ≤ 1,000,000, 1 ≤ K ≤ 300,000, 1 ≤ X ≤ N) 둘째 줄부터 M개의 줄에 걸쳐서 두 개

www.acmicpc.net

bfs와 다익스트라 두 가지방법 모두 사용하였습니다.

이 문제는 방향그래프이므로 u v 로 입력이 오면 u -> v로 받아야합니다.

 

먼저 다익스트라 알고리즘 방법으로는 가중치가 주어지지 않았기때문에 1로 두고 다익스트라 알고리즘을 이용하여 start에서 각 노드까지 최단거리를 다 구해줍니다.

최단거리가 K인 노드가 있으면 오름차순으로 출력해주고, 없으면 -1을 출력합니다.

 

bfs 방법으로는 start에서부터 시작하여 bfs를 K번 진행합니다.

bfs로 탐색하면서 각 노드까지의 거리를 갱신해줍니다.

최단거리가 K인 노드가 있으면 오름차순으로 출력해주고, 없으면 -1을 출력합니다.

 

다익스트라 사용
bfs 사용

 

다익스트라는 모든 정점까지의 최단거리를 다 구해주기 때문에 시간 상으로는 bfs가 훨씬 효율적입니다.

 

 

[dijkstra]

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
#include <iostream>
#include <queue>
#include <vector>
#define INF 1000000000
using namespace std;
 
vector<pair<intint> > list[300001];
int d[300001];
int N, M, K, start;
 
void solve() {
    bool chk = false;
    for (int i = 1; i <= N; i++) {
        if (d[i] == K) {
            chk = true;
            cout << i << '\n';
        }
    }
 
    if (!chk) cout << "-1\n";
}
 
void dijkstra() {
    d[start] = 0;
    priority_queue<pair<intint> > q;
    q.push({ start, 0 });
    while (!q.empty()) {
        int now = q.top().first;
        int dis = -q.top().second;
        q.pop();
 
        if (d[now] < dis) continue;
 
        for (int i = 0; i < list[now].size(); i++) {
            int next = list[now][i].first;
            int nextdis = dis + list[now][i].second;
 
            if (d[next] > nextdis) {
                d[next] = nextdis;
                q.push({ next, -nextdis });
            }
        }
    }
}
 
void init() {
    for (int i = 1; i <= N; i++) {
        d[i] = INF;
    }
}
 
void input() {
    int u, v;
    cin >> N >> M >> K >> start;
    init();
 
    while (M--) {
        cin >> u >> v;
        list[u].push_back({ v,1 });
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    dijkstra();
    solve();
 
    return 0;
}
cs

 

 

[bfs]

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
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
 
vector<int> list[300001];
queue<int> q;
int d[300001];
int N, M, K, start;
 
void solve() {
    bool chk = false;
    for (int i = 1; i <= N; i++) {
        if (d[i] == K) {
            chk = true;
            cout << i << '\n';
        }
    }
 
    if (!chk) cout << "-1\n";
}
 
void bfs() {
    q.push(start);
    d[start] = 0;
    for (int t = 1; t <= K; t++) {
        int qsize = q.size();
        while (qsize--) {
            int x = q.front();
            q.pop();
 
            for (int i = 0; i < list[x].size(); i++) {
                int next = list[x][i];
                if (d[next] != -1continue;
                
                q.push(next);
                d[next] = t;
            }
        }
    }
}
 
void input() {
    int u, v;
    cin >> N >> M >> K >> start;
    while (M--) {
        cin >> u >> v;
        list[u].push_back(v);
    }
    memset(d, -1sizeof(d));
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    bfs();
    solve();
 
    return 0;
}
cs

'algorithm > dijkstra' 카테고리의 다른 글

boj 4485 녹색 옷 입은 애가 젤다지?  (0) 2021.03.23
boj 14496 그대, 그머가 되어  (0) 2021.03.22

www.acmicpc.net/problem/2589

 

2589번: 보물섬

보물섬 지도를 발견한 후크 선장은 보물을 찾아나섰다. 보물섬 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다. 각 칸은 육지(L)나 바다(W)로 표시되어 있다. 이 지도에서

www.acmicpc.net

칸이 육지인 곳에서 bfs를 돌려서 거리가 가장 긴 시간을 출력하는 문제입니다.

이 문제는 육지인 모든 칸을 시작점으로 잡고 bfs를 돌려주면 되겠습니다.

한 번의 bfs가 끝나면 visit배열을 초기화 해주어야합니다.

 

 

[C++]

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
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
 
typedef struct Point {
    int x;
    int y;
    int cnt;
}Point;
 
char list[60][60];
bool visit[60][60];
int direct[4][2= { {0,1},{1,0},{0,-1},{-1,0} };
int N, M, ans;
 
void bfs(int sx, int sy) {
    queue<Point> q;
    q.push({ sx,sy,0 });
    visit[sx][sy] = true;
    while (!q.empty()) {
        int x = q.front().x;
        int y = q.front().y;
        int cnt = q.front().cnt;
        q.pop();
 
        ans = max(ans, cnt);
        for (int i = 0; i < 4; i++) {
            int nx = x + direct[i][0];
            int ny = y + direct[i][1];
 
            if (nx < 0 || ny < 0 || nx >= N || ny >= M) continue;
            if (visit[nx][ny] || list[nx][ny] == 'W'continue;
 
            q.push({ nx,ny,cnt + 1 });
            visit[nx][ny] = true;
        }
    }
}
 
void func() {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (list[i][j] == 'W'continue;
 
            bfs(i, j);
            memset(visit, falsesizeof(visit));
        }
    }
 
    cout << ans << '\n';
}
 
void input() {
    cin >> N >> M;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> list[i][j];
        }
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
 
    return 0;
}
cs

 

 

[Java]

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static char list[][] = new char[60][60];
    static boolean visit[][] = new boolean[60][60];
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static int N, M, ans;
 
    static void bfs(int sx, int sy) {
        Deque<int[]> dq = new ArrayDeque<>();
        dq.add(new int[] { sx, sy, 0 });
        visit[sx][sy] = true;
        while (!dq.isEmpty()) {
            int x = dq.peek()[0];
            int y = dq.peek()[1];
            int cnt = dq.poll()[2];
 
            ans = Math.max(ans, cnt);
            for (int i = 0; i < 4; i++) {
                int nx = x + direct[i][0];
                int ny = y + direct[i][1];
 
                if (nx < 0 || ny < 0 || nx >= N || ny >= M)
                    continue;
                if (visit[nx][ny] || list[nx][ny] == 'W')
                    continue;
 
                dq.add(new int[] { nx, ny, cnt + 1 });
                visit[nx][ny] = true;
            }
        }
    }
 
    static void func() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (list[i][j] == 'W')
                    continue;
 
                bfs(i, j);
                for (int k = 0; k < N; k++)
                    Arrays.fill(visit[k], false);
            }
        }
        
        System.out.println(ans);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
 
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            list[i] = st.nextToken().toCharArray();
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

 

'algorithm > bfs' 카테고리의 다른 글

boj 9205 맥주 마시면서 걸어가기  (0) 2021.03.25
boj 1600 말이 되고픈 원숭이  (0) 2021.03.24
boj 11559 Puyo Puyo  (0) 2021.02.26
boj 15653 구슬 탈출 4  (0) 2021.02.22
boj 1525 퍼즐  (0) 2021.02.19

+ Recent posts