www.acmicpc.net/problem/11559

 

11559번: Puyo Puyo

총 12개의 줄에 필드의 정보가 주어지며, 각 줄에는 6개의 문자가 있다. 이때 .은 빈공간이고 .이 아닌것은 각각의 색깔의 뿌요를 나타낸다. R은 빨강, G는 초록, B는 파랑, P는 보라, Y는 노랑이다.

www.acmicpc.net

같은 색 뿌요가 4개이상 상하좌우 4방향으로 연결되어있으면 터집니다.

뿌요들이 없어지고나서 남은 뿌요들은 아래로 모두 이동시켜줍니다.

그렇게 모인 뿌요들 중 같은 색 뿌요가 4개이상 모이게 되면 다시 터집니다. => 연쇄가 추가됩니다.

이 과정을 뿌요가 터지지 않을때까지 반복하여 몇 연쇄가 일어나는지 출력하는 문제입니다.

 

저의 로직은 다음과 같습니다.

1. 12 * 6 배열을 돌면서 뿌요가 있는 칸이면 bfs로 몇개가 모여있는지 확인

2. 4개이상 모여있으면 모여있는 뿌요들 제거 => 이 때 제거할 뿌요는 ArrayList에 넣었습니다.

3. 제거된 뿌요가 없으면 t - 1를 출력 후 리턴하고 아니면 다음으로 넘어갑니다.

4. 제거된 뿌요로 인해 빈칸을 위의 뿌요들로 채워줍니다. (뿌요들을 아래로 내려줍니다.)

 

3번에서 t - 1을 출력하는 이유는 몇 번 연쇄인지 출력하는 문제인데 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
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
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 char list[][] = new char[12][6];
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static ArrayList<int[]> erasepoint = new ArrayList<>();
    static boolean visit[][] = new boolean[12][6];
    static int cnt;
 
    static void bfs(int sx, int sy) {
        Deque<int[]> dq = new ArrayDeque<>();
        dq.add(new int[] { sx, sy });
        visit[sx][sy] = true;
        cnt = 0;
        while (!dq.isEmpty()) {
            int x = dq.peek()[0];
            int y = dq.poll()[1];
            erasepoint.add(new int[] { x, y });
            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 >= 12 || ny >= 6)
                    continue;
                if (visit[nx][ny] || list[nx][ny] != list[x][y])
                    continue;
 
                dq.add(new int[] { nx, ny });
                visit[nx][ny] = true;
            }
        }
    }
 
    static void func() {
        for (int t = 1;; t++) {
            boolean chk = false;
            for (int i = 0; i < 12; i++)
                Arrays.fill(visit[i], false);
 
            for (int i = 0; i < 12; i++) {
                for (int j = 0; j < 6; j++) {
                    if (list[i][j] == '.')
                        continue;
                    bfs(i, j);
                    if (cnt >= 4) {
                        chk = true;
                        for (int xy[] : erasepoint) {
                            list[xy[0]][xy[1]] = '.';
                        }
                    }
                    erasepoint.clear();
                }
            }
 
            if (!chk) {
                System.out.println(t - 1);
                return;
            }
 
            for (int i = 10; i >= 0; i--) {
                for (int j = 0; j < 6; j++) {
                    if (list[i][j] == '.')
                        continue;
 
                    for (int k = i + 1; k < 12; k++) {
                        if (list[k][j] != '.') {
                            char tmp = list[i][j];
                            list[i][j] = list[k - 1][j];
                            list[k - 1][j] = tmp;
                            break;
                        } else {
                            if (k == 11) {
                                char tmp = list[i][j];
                                list[i][j] = list[k][j];
                                list[k][j] = tmp;
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
 
    static void input() throws Exception {
        for (int i = 0; i < 12; 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 1600 말이 되고픈 원숭이  (0) 2021.03.24
boj 2589 보물섬  (0) 2021.03.16
boj 15653 구슬 탈출 4  (0) 2021.02.22
boj 1525 퍼즐  (0) 2021.02.19
boj 7576 토마토  (0) 2021.02.19

www.acmicpc.net/problem/15653

 

15653번: 구슬 탈출 4

첫 번째 줄에는 보드의 세로, 가로 크기를 의미하는 두 정수 N, M (3 ≤ N, M ≤ 10)이 주어진다. 다음 N개의 줄에 보드의 모양을 나타내는 길이 M의 문자열이 주어진다. 이 문자열은 '.', '#', 'O', 'R', 'B'

www.acmicpc.net

보드를 4방향으로 기울여 구슬을 구멍으로 빼내는데 걸리는 최소 횟수를 출력하는 문제입니다. 구멍을 통해 빼낼 수 없으면 -1을 출력합니다.

 

시뮬레이션으로 구슬을 이동시켜야하며, 4방향으로 기울이는 것은 bfs를 이용하였습니다.

우선 큐에 입력으로 받은 빨간 구슬의 좌표, 파란 구슬의 좌표, 그리고 0(움직인 횟수)를 넣습니다.

그 다음 bfs로 구슬을 움직여줍니다.

 

구슬을 움직일 때는

1. 빨간 구슬과 파란 구슬을 벽이나 구멍이 있을때까지 움직여줍니다.

2. 만약 파란 구슬이 도중에 탈출했다면 continue (파란 구슬은 탈출하면 안됩니다.)

3. 파란 구슬이 탈출 안했고, 빨간 구슬이 탈출 했으면 cnt + 1 출력

4. 둘 다 탈출 못했으면 큐에 넣기 전에 구슬들이 겹칠 가능성이 존재하므로 확인해줍니다.

5. 구슬들이 겹쳐있으면 원래의 자리와 거리를 구해 먼 쪽이 한칸 뒤로 이동합니다.

6. 이제 다음 칸인 (nrx, nry), (nbx, nby)의 방문했는지 확인해줍니다.

7. 모두 통과되면 방문 체크를 해주고, 큐에 넣어줍니다.

8. 만약 큐가 비어있게 되면 탈출을 못했다는 뜻이므로 -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
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
 
typedef struct point {
    int rx;
    int ry;
    int bx;
    int by;
    int cnt;
}point;
 
queue<point> q;
bool visit[11][11][11][11];
char list[11][11];
int direct[4][2= { {0,1},{1,0},{0,-1},{-1,0} };
int N, M;
 
void bfs() {
    while (!q.empty()) {
        int rx = q.front().rx;
        int ry = q.front().ry;
        int bx = q.front().bx;
        int by = q.front().by;
        int cnt = q.front().cnt;
        q.pop();
        
        for (int i = 0; i < 4; i++) {
            int nrx = rx;
            int nry = ry;
 
            bool redchk = false;
            bool bluechk = false;
            while (1) {
                nrx += direct[i][0];
                nry += direct[i][1];
 
                if (list[nrx][nry] == '#') {
                    nrx -= direct[i][0];
                    nry -= direct[i][1];
                    break;
                }
                else if (list[nrx][nry] == 'O') {
                    redchk = true;
                    break;
                }
            }
 
            int nbx = bx;
            int nby = by;
 
            while (1) {
                nbx += direct[i][0];
                nby += direct[i][1];
 
                if (list[nbx][nby] == '#') {
                    nbx -= direct[i][0];
                    nby -= direct[i][1];
                    break;
                }
                else if (list[nbx][nby] == 'O') {
                    bluechk = true;
                    break;
                }
            }
 
            if (bluechk) continue;
            else if (redchk) {
                cout << cnt + 1 << '\n';
                return;
            }
 
            if (nrx == nbx && nry == nby) {
                int reddis = abs(nrx - rx) + abs(nry - ry);
                int bluedis = abs(nbx - bx) + abs(nby - by);
 
                if (reddis > bluedis) {
                    nrx -= direct[i][0];
                    nry -= direct[i][1];
                }
                else {
                    nbx -= direct[i][0];
                    nby -= direct[i][1];
                }
            }
 
            if (visit[nrx][nry][nbx][nby]) continue;
 
            q.push({ nrx,nry,nbx,nby,cnt + 1 });
            visit[nrx][nry][nbx][nby] = true;
        }
    }
 
    cout << "-1\n";
}
 
void input() {
    int rx, ry, bx, by;
    cin >> N >> M;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> list[i][j];
            if (list[i][j] == 'B') {
                bx = i;
                by = j;
            }
            else if (list[i][j] == 'R') {
                rx = i;
                ry = j;
            }
        }
    }
 
    q.push({ rx,ry,bx,by,0 });
    visit[rx][ry][bx][by] = true;
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    bfs();
 
    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
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;
 
public class Main {
    static class Pair {
        int rx;
        int ry;
        int bx;
        int by;
        int cnt;
 
        public Pair(int rx, int ry, int bx, int by, int cnt) {
            this.rx = rx;
            this.ry = ry;
            this.bx = bx;
            this.by = by;
            this.cnt = cnt;
        }
    }
 
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Deque<Pair> dq = new ArrayDeque<>();
    static boolean visit[][][][] = new boolean[11][11][11][11];
    static char list[][] = new char[11][11];
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static int N, M;
 
    static void bfs() {
        while (!dq.isEmpty()) {
            int rx = dq.peek().rx;
            int ry = dq.peek().ry;
            int bx = dq.peek().bx;
            int by = dq.peek().by;
            int cnt = dq.poll().cnt;
 
            for (int i = 0; i < 4; i++) {
                int nrx = rx;
                int nry = ry;
                boolean redchk = false;
                while (true) {
                    nrx += direct[i][0];
                    nry += direct[i][1];
 
                    if (list[nrx][nry] == '#') {
                        nrx -= direct[i][0];
                        nry -= direct[i][1];
                        break;
                    }
                    if (list[nrx][nry] == 'O') {
                        redchk = true;
                        break;
                    }
                }
 
                int nbx = bx;
                int nby = by;
                boolean bluechk = false;
                while (true) {
                    nbx += direct[i][0];
                    nby += direct[i][1];
 
                    if (list[nbx][nby] == '#') {
                        nbx -= direct[i][0];
                        nby -= direct[i][1];
                        break;
                    }
                    if (list[nbx][nby] == 'O') {
                        bluechk = true;
                        break;
                    }
                }
 
                if (bluechk)
                    continue;
                else if (redchk) {
                    System.out.println(cnt + 1);
                    return;
                }
 
                if (nrx == nbx && nry == nby) {
                    int reddis = Math.abs(nrx - rx) + Math.abs(nry - ry);
                    int bluedis = Math.abs(nbx - bx) + Math.abs(nby - by);
 
                    if (bluedis < reddis) {
                        nrx -= direct[i][0];
                        nry -= direct[i][1];
                    } else {
                        nbx -= direct[i][0];
                        nby -= direct[i][1];
                    }
                }
 
                if (visit[nrx][nry][nbx][nby])
                    continue;
 
                dq.add(new Pair(nrx, nry, nbx, nby, cnt + 1));
                visit[nrx][nry][nbx][nby] = true;
            }
        }
 
        System.out.println(-1);
    }
 
    static void input() throws Exception {
        int rx = 0, ry = 0, bx = 0, by = 0;
        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] == 'R') {
                    rx = i;
                    ry = j;
                } else if (list[i][j] == 'B') {
                    bx = i;
                    by = j;
                }
            }
        }
 
        dq.add(new Pair(rx, ry, bx, by, 0));
        visit[rx][ry][bx][by] = true;
    }
 
    public static void main(String[] args) throws Exception {
        input();
        bfs();
    }
}
cs

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

boj 2589 보물섬  (0) 2021.03.16
boj 11559 Puyo Puyo  (0) 2021.02.26
boj 1525 퍼즐  (0) 2021.02.19
boj 7576 토마토  (0) 2021.02.19
boj 17135 캐슬 디펜스  (0) 2021.02.17

 

www.acmicpc.net/problem/1525

 

1525번: 퍼즐

세 줄에 걸쳐서 표에 채워져 있는 아홉 개의 수가 주어진다. 한 줄에 세 개의 수가 주어지며, 빈 칸은 0으로 나타낸다.

www.acmicpc.net

3 * 3 퍼즐을 이동시켜서 위와같은 상태로 만들고, 이동의 최소 횟수를 출력하고, 불가능한 경우 -1를 출력합니다.

 

저는 3 * 3 퍼즐을 String으로 변환시켰습니다.

1 0 3
4 2 5
7 8 6

입력이 이렇게 주어지면 "103425786"을 만든 다음 bfs를 돌렸습니다. (방문체크도 Set<String>으로 하였습니다.)

그리고 각 칸에서 움직일 수 있는 공간을 ArrayList배열을 만들어서 모두 만들어줍니다.

왼쪽 위 칸 번호가 0번부터 시작해서 오른쪽 아래 칸 번호가 8번이되어 

0 -> 1, 3

1 -> 0, 2, 4

2 -> 1, 5

3 -> 0, 4, 6

4 -> 1, 3, 5, 7

5 -> 2, 4, 8

6 -> 3, 7

7 -> 4, 6, 8

8 -> 5, 7

이렇게 그래프를 연결시킬 수 있습니다.

 

이제 bfs를 돌려줍니다.

덱에 입력받은 문자열(str), 0의 위치(idx), 움직인 횟수(cnt)를 넣어줍니다.

bfs 과정에서는 현재 문자열에서 idx위치와 next위치의 문자열을 서로 바꿔줍니다.

그리고 중복체크를 하고, 덱에 넣어주는 방식으로 하였습니다.

 

덱에서 꺼낸 문자열이 ans인 "123456780"과 같으면 cnt를 출력하고 리턴합니다.

만약 ans와 같은 문자열이 나오지 않았는데 덱이 비어있게되면 "123456780"을 만들수 없으므로 -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
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
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <set>
using namespace std;
 
typedef struct list {
    string now;
    int idx;
    int cnt;
}list;
 
queue<list> q;
set<string> s;
vector<int> v[9];
string ans = "123456780", str = "";
 
void init() {
    v[0].push_back(1);
    v[0].push_back(3);
 
    v[1].push_back(0);
    v[1].push_back(2);
    v[1].push_back(4);
 
    v[2].push_back(1);
    v[2].push_back(5);
 
    v[3].push_back(0);
    v[3].push_back(4);
    v[3].push_back(6);
 
    v[4].push_back(1);
    v[4].push_back(3);
    v[4].push_back(5);
    v[4].push_back(7);
 
    v[5].push_back(2);
    v[5].push_back(4);
    v[5].push_back(8);
 
    v[6].push_back(3);
    v[6].push_back(7);
 
    v[7].push_back(4);
    v[7].push_back(6);
    v[7].push_back(8);
 
    v[8].push_back(5);
    v[8].push_back(7);
}
 
void bfs() {
    while (!q.empty()) {
        string now = q.front().now;
        int idx = q.front().idx;
        int cnt = q.front().cnt;
        q.pop();
 
        if (!now.compare(ans)) {
            cout << cnt << '\n';
            return;
        }
 
        for (int i = 0; i < v[idx].size(); i++) {
            int next = v[idx][i];
            string tmp = now;
            swap(tmp[idx], tmp[next]);
 
            if (s.find(tmp) != s.end()) continue;
 
            q.push({ tmp, next, cnt + 1 });
            s.insert(tmp);
        }
    }
 
    cout << "-1\n";
}
 
void input() {
    int k = 0;
    string tmp = "";
    for (int i = 0; i < 9; i++) {
        cin >> tmp;
        str += tmp;
 
        if (tmp[0== '0') {
            k = i;
        }
    }
 
    q.push({ str, k, 0 });
    s.insert(str);
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    init();
    input();
    bfs();
 
    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
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
114
115
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
 
public class Main {
    static class Pair {
        String now;
        int idx;
        int cnt;
 
        public Pair(String now, int idx, int cnt) {
            this.now = now;
            this.idx = idx;
            this.cnt = cnt;
        }
    }
 
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static String ans = "123456780";
    static ArrayList<Integer> list[] = new ArrayList[9];
    static String str = "";
 
    static void init() {
        for (int i = 0; i < 9; i++)
            list[i] = new ArrayList<>();
 
        list[0].add(1);
        list[0].add(3);
 
        list[1].add(0);
        list[1].add(2);
        list[1].add(4);
 
        list[2].add(1);
        list[2].add(5);
 
        list[3].add(0);
        list[3].add(4);
        list[3].add(6);
 
        list[4].add(1);
        list[4].add(3);
        list[4].add(5);
        list[4].add(7);
 
        list[5].add(2);
        list[5].add(4);
        list[5].add(8);
 
        list[6].add(3);
        list[6].add(7);
 
        list[7].add(4);
        list[7].add(6);
        list[7].add(8);
 
        list[8].add(5);
        list[8].add(7);
    }
 
    static void bfs() {
        Set<String> s = new HashSet<>();
        Deque<Pair> dq = new ArrayDeque<>();
        dq.add(new Pair(str, str.indexOf("0"), 0));
        s.add(new String(str));
        while (!dq.isEmpty()) {
            String now = dq.peek().now;
            int idx = dq.peek().idx;
            int cnt = dq.poll().cnt;
 
            if (now.equals(ans)) {
                System.out.println(cnt);
                return;
            }
 
            for (int i = 0; i < list[idx].size(); i++) {
                int next = list[idx].get(i);
                char newstr[] = new String(now).toCharArray();
                char tmp = newstr[idx];
                newstr[idx] = newstr[next];
                newstr[next] = tmp;
 
                String s1 = String.valueOf(newstr);
                if (s.contains(s1))
                    continue;
 
                dq.add(new Pair(s1, next, cnt + 1));
                s.add(new String(s1));
            }
        }
 
        System.out.println(-1);
    }
 
    static void input() throws Exception {
        for (int i = 0; i < 3; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < 3; j++) {
                str += st.nextToken();
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        init();
        input();
        bfs();
    }
}
cs

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

boj 11559 Puyo Puyo  (0) 2021.02.26
boj 15653 구슬 탈출 4  (0) 2021.02.22
boj 7576 토마토  (0) 2021.02.19
boj 17135 캐슬 디펜스  (0) 2021.02.17
boj 16236 아기 상어  (0) 2021.02.14

www.acmicpc.net/problem/7576

 

7576번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M,N ≤ 1,000 이다. 둘째 줄부터는 하나의 상자에 저장된 토마토

www.acmicpc.net

bfs를 이용하여 익은 토마토와 근접해있는 토마토를 익게해서 모든 토마토를 익혀야합니다.

하지만 토마토가 들어있지 않은 칸이 있기때문에 모든 토마토가 익지 않을 수도 있습니다.

그리고 입력으로 이미 모든 토마토가 익어있으면 0을 출력해야합니다.

 

우선 입력을 받고, 0의 갯수(ans)를 모두 세어 유지합니다.

그리고 1을 입력받으면 덱에 넣고 방문처리도 해줍니다. (bfs 사용)

그 다음 bfs를 돌리기 전에 이미 ans가 0이면 0을 출력하고 리턴합니다.

 

확인이 끝나면 bfs를 돌려줍니다.

하루에 한칸씩 번지기때문에 덱에 있던 좌표들만 돌려야합니다. (t로 날짜 계산)

for문을 덱이 비어있지 않을동안 돌려주고 현재 덱의 크기를 size에 넣어서 size 만큼만 bfs를 돌려줍니다. (1일치)

 

이후에 ans가 0이 되면 모두 익었다는 뜻이므로 t를 출력합니다.

ans가 0이 되지 않았는데 덱이 비어버리면 모두 익지 않았다는 뜻이므로 -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
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <queue>
using namespace std;
 
queue<pair<intint> > q;
int direct[4][2= { {0,1},{1,0},{0,-1},{-1,0} };
bool visit[1001][1001];
int list[1001][1001];
int N, M, ans;
 
void bfs() {
    int t = 1;
    for (; !q.empty(); t++) {
        int qsize = q.size();
        while (qsize--) {
            int x = q.front().first;
            int y = q.front().second;
            q.pop();
 
            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] == -1continue;
 
                q.push({ nx,ny });
                visit[nx][ny] = true;
                ans--;
            }
        }
 
        if (!ans) {
            cout << t << '\n';
            return;
        }
    }
 
    cout << "-1\n";
}
 
void func() {
    if (!ans) {
        cout << "0\n";
        return;
    }
 
    bfs();
}
 
void input() {
    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])
                ans++;
            else if (list[i][j] == 1) {
                q.push({ i,j });
                visit[i][j] = true;
            }
        }
    }
}
 
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
72
73
74
75
76
77
78
79
80
81
82
83
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 direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static boolean visit[][];
    static int list[][];
    static int N, M, ans;
 
    static void bfs() {
        int t = 1;
        for (; !dq.isEmpty(); t++) {
            int size = dq.size();
 
            while (size-- > 0) {
                int x = dq.peekFirst()[0];
                int y = dq.pollFirst()[1];
 
                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] == -1 || visit[nx][ny])
                        continue;
 
                    visit[nx][ny] = true;
                    dq.addLast(new int[] { nx, ny });
                    ans--;
                }
            }
 
            if (ans == 0)
                break;
        }
        if (ans == 0)
            System.out.println(t);
        else
            System.out.println(-1);
    }
 
    static void func() {
        if (ans == 0) {
            System.out.println(0);
            return;
        }
 
        bfs();
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        M = Integer.parseInt(st.nextToken());
        N = Integer.parseInt(st.nextToken());
        list = new int[N][M];
        visit = new boolean[N][M];
 
        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());
                if (list[i][j] == 0)
                    ans++;
                else if (list[i][j] == 1) {
                    dq.addLast(new int[] { i, j });
                    visit[i][j] = true;
                }
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func();
    }
}
cs

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

boj 15653 구슬 탈출 4  (0) 2021.02.22
boj 1525 퍼즐  (0) 2021.02.19
boj 17135 캐슬 디펜스  (0) 2021.02.17
boj 16236 아기 상어  (0) 2021.02.14
boj 10026 적록색약  (0) 2021.02.13

www.acmicpc.net/problem/17135

 

17135번: 캐슬 디펜스

첫째 줄에 격자판 행의 수 N, 열의 수 M, 궁수의 공격 거리 제한 D가 주어진다. 둘째 줄부터 N개의 줄에는 격자판의 상태가 주어진다. 0은 빈 칸, 1은 적이 있는 칸이다.

www.acmicpc.net

알고리즘 분류는 bfs지만 조합 + 정렬 + 시뮬레이션 + 구현 등 사용해야할 기법이 많았습니다.

 

제가 처음 접근한 방법은

우선 조합으로 궁수가 있을 자리를 모두 구해준 다음

bfs로 4방향 탐색하여 공격가능한 적을 모두 담아놓고 정렬하여 맨 첫번째에 있는 적만 제거하였고

그 다음 적들을 모두 아래로 내려 다음 bfs탐색을 하는 방식이었습니다.

 

위의 방법으로 AC를 받았지만 시간적인 손해가 많다는 생각이 들었고, 시간을 줄이기위해 다른 방법을 생각하였습니다.

 

궁수는 항상 N + 1번째 행에 있기때문에 밑을 볼 필요가 없습니다. 그래서 왼쪽, 위, 오른쪽만 탐색하면 됩니다.

여기서 문제 조건을 보시면 가장 가까운 적이 여러명이면 가장 왼쪽에 있는 적을 공격한다고 나와있습니다.

위의 조건에서 왼쪽 -> 위 -> 오른쪽 방향 순서로 탐색하면 무조건 공격해야할 대상을 먼저 찾는다는 결론이 나왔습니다. 이제 정렬은 사용하지 않아도됩니다.

 

그 다음 여러명의 궁수가 한명의 적을 공격할 수 있기때문에 궁수가 공격할 대상을 찾으면

boolean배열을 사용하여 true로 바꿔주었고, 이중 for문으로 true인 좌표의 list를 0으로 바꿔주었지만

int배열을 사용하여 모든 좌표를 다 넣어주었고, 하나의 for문으로 해결할 수 있었습니다.

 

마지막으로 적을 제거하고 난 후에 이중 for문을 돌려서 적이 모두 제거되었는지 확인하였습니다.

제거되었으면 break를 해주고, 아니면 적들을 아래로 내려야합니다.

하지만 저는 적들을 아래로 내리는것보다 궁수를 위로 올리는 것이 시간상 효율적이라는 것을 깨닫고 궁수를 위로 올리기 위해 n--를 하였습니다.

 

최종적으로 저의 로직은 이렇습니다.

1. 조합으로 궁수를 배치

2. bfs로 3방향 탐색하여 공격할 수 있는 적을 탐색 (적을 찾거나 D보다 거리가 커지면 break)

3. 2번에서 찾은 적 제거

4. 적이 모두 제거되었는지 확인

5. 적이 모두 제거되었으면 break, 아니면 궁수 한 칸 위로 이동(n--)

 

자바에서 Collection사용이 많아지면 시간적으로 비효율적이라고 생각해서 배열을 최대한 사용하였습니다.

 

 

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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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 boolean visit[][];
    static int direct[][] = { { 0-1 }, { -10 }, { 01 } };
    static int list[][], copylist[][], attacker[], rkill[][];
    static int N, M, D, ans, kidx;
 
    static void bfs() {
        int n = N;
        int sum = 0;
        Deque<int[]> dq = new ArrayDeque<int[]>();
        ArrayList<int[]> kill = new ArrayList<>();
        while (true) {
            for (int k = 0; k < 3; k++) {
                dq.addLast(new int[] { n, attacker[k], 0 });
                for (int i = 0; i < n; i++)
                    Arrays.fill(visit[i], false);
 
                while (!dq.isEmpty()) {
                    int x = dq.peekFirst()[0];
                    int y = dq.peekFirst()[1];
                    int cnt = dq.pollFirst()[2];
 
                    if (cnt == D) {
                        dq.clear();
                        break;
                    }
                    boolean chk = false;
                    for (int i = 0; i < 3; 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])
                            continue;
                        if (copylist[nx][ny] == 1) {
                            chk = true;
                            kill.add(new int[] { nx, ny, cnt + 1 });
                            break;
                        } else {
                            dq.addLast(new int[] { nx, ny, cnt + 1 });
                            visit[nx][ny] = true;
                        }
                    }
                    if (chk)
                        break;
                }
                dq.clear();
 
                if (kill.isEmpty())
                    continue;
 
                rkill[kidx][0= kill.get(0)[0];
                rkill[kidx++][1= kill.get(0)[1];
                kill.clear();
            }
 
            for (int i = 0; i < kidx; i++) {
                if (copylist[rkill[i][0]][rkill[i][1]] == 1) {
                    copylist[rkill[i][0]][rkill[i][1]] = 0;
                    sum++;
                }
            }
            kidx = 0;
 
            boolean allkill = false;
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < M; j++) {
                    if (copylist[i][j] == 1) {
                        allkill = true;
                        break;
                    }
                }
                if (allkill)
                    break;
            }
            if (!allkill)
                break;
            n--;
        }
 
        ans = Math.max(ans, sum);
    }
 
    static void func(int idx, int cnt) {
        if (cnt == 3) {
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++)
                    copylist[i][j] = list[i][j];
            }
            bfs();
            return;
        }
 
        for (int i = idx; i < M; i++) {
            attacker[cnt] = i;
            func(i + 1, cnt + 1);
        }
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        D = Integer.parseInt(st.nextToken());
        list = new int[N][M];
        copylist = new int[N][M];
        attacker = new int[3];
        visit = new boolean[N][M];
        rkill = new int[226][2];
 
        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(00);
        System.out.println(ans);
    }
}
cs

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

boj 1525 퍼즐  (0) 2021.02.19
boj 7576 토마토  (0) 2021.02.19
boj 16236 아기 상어  (0) 2021.02.14
boj 10026 적록색약  (0) 2021.02.13
boj 2206 벽 부수고 이동하기  (0) 2021.02.13

www.acmicpc.net/problem/16236

 

16236번: 아기 상어

N×N 크기의 공간에 물고기 M마리와 아기 상어 1마리가 있다. 공간은 1×1 크기의 정사각형 칸으로 나누어져 있다. 한 칸에는 물고기가 최대 1마리 존재한다. 아기 상어와 물고기는 모두 크기를 가

www.acmicpc.net

상어가 지나갈 수 있는 경우는

1. 자신의 크기보다 작거나 같은 물고기가 있는 경우

2. 빈 칸

이렇게 두 가지이며, 상어는 자신보다 작은 물고기만 먹을 수 있습니다.

그리고 자신의 크기와 같은 수의 물고기를 먹으면 크기가 1 커집니다.

 

상어가 먹을 수 있는 물고기를 bfs로 찾고,

먹을 수 있는 물고기가 여러마리면 그 중 가장 가까운 물고기, 가장 위에 있는 물고기, 가장 왼쪽에 있는 물고기 순으로 먹습니다.

 

저는 bfs로 순회하며 먹을 수 있는 물고기를 ArrayList에 담았고 위의 조건 순으로 정렬하였습니다.

그럼 0번 인덱스에 있는 물고기를 먹으면 되고, 그 물고기까지의 거리를 ans에 더해주고, 그 위치에서 다시 시작합니다.

위의 과정을 물고기를 먹을 수 있을때까지 반복해줍니다.

 

 

[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
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
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
 
queue<pair<intint> > q;
int list[21][21];
bool visit[21][21];
int direct[4][2= { {0,1},{1,0},{0,-1},{-1,0} };
int N, ans;
 
bool cmp(pair<intint> a, pair<intint> b) {
    if (a.first < b.first) return true;
    else if (a.first == b.first) {
        if (a.second < b.second) return true;
        else return false;
    }
    else return false;
}
 
void bfs() {
    int ssize = 2;
    int eat = 0;
    while (1) {
        bool chk = false;
        vector<pair<intint> > v;
        for (int t = 1; ; t++) {
            int qsize = q.size();
            while (qsize--) {
                int x = q.front().first;
                int y = q.front().second;
                q.pop();
 
                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 >= N) continue;
                    if (visit[nx][ny]) continue;
                    if (list[nx][ny] > ssize) continue;
 
                    if (list[nx][ny] && list[nx][ny] < ssize) {
                        v.push_back({ nx,ny });
                    }
                    q.push({ nx,ny });
                    visit[nx][ny] = true;
                }
            }
 
            if (!v.empty()) {
                ans += t;
                break;
            }
            if (q.empty()) {
                chk = true;
                break;
            }
        }
        if (chk) break;
 
        sort(v.begin(), v.end(), cmp);
        int x = v[0].first;
        int y = v[0].second;
        list[x][y] = 0;
        eat++;
        if (eat == ssize) {
            ssize++;
            eat = 0;
        }
        v.clear();
        memset(visit, falsesizeof(visit));
        while (!q.empty()) q.pop();
        q.push({ x,y });
        visit[x][y] = true;
    }
 
    cout << ans << '\n';
}
 
void input() {
    cin >> N;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            cin >> list[i][j];
            if (list[i][j] == 9) {
                q.push({ i,j });
                visit[i][j] = true;
                list[i][j] = 0;
            }
        }
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    bfs();
 
    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
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.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.StringTokenizer;
import java.io.BufferedReader;
 
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[21][21];
    static boolean visit[][] = new boolean[21][21];
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static int N, ans;
 
    static void bfs() {
        int size = 2;
        int eat = 0;
        while (true) {
            boolean chk = false;
            ArrayList<int[]> eatlist = new ArrayList<>();
            for (int t = 1;; t++) {
                int qsize = dq.size();
                while (qsize-- > 0) {
                    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 (nx < 0 || ny < 0 || nx >= N || ny >= N)
                            continue;
                        if (visit[nx][ny])
                            continue;
                        if (list[nx][ny] > size)
                            continue;
 
                        if (list[nx][ny] != 0 && list[nx][ny] < size) {
                            eatlist.add(new int[] { nx, ny });
                        }
                        dq.add(new int[] { nx, ny });
                        visit[nx][ny] = true;
                    }
                }
 
                if (!eatlist.isEmpty()) {
                    ans += t;
                    break;
                }
                if (dq.isEmpty()) {
                    chk = true;
                    break;
                }
            }
 
            if (chk)
                break;
 
            Collections.sort(eatlist, new Comparator<int[]>() {
                @Override
                public int compare(int[] a, int[] b) {
                    if (a[0== b[0])
                        return a[1- b[1];
                    else
                        return a[0- b[0];
                }
            });
 
            int x = eatlist.get(0)[0];
            int y = eatlist.get(0)[1];
            list[x][y] = 0;
            eat++;
            if (eat == size) {
                eat = 0;
                size++;
            }
 
            dq.clear();
            eatlist.clear();
            for (int i = 0; i < N; i++)
                Arrays.fill(visit[i], false);
            dq.add(new int[] { x, y });
            visit[x][y] = true;
        }
        System.out.println(ans);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < N; j++) {
                list[i][j] = Integer.parseInt(st.nextToken());
                if (list[i][j] == 9) {
                    list[i][j] = 0;
                    dq.add(new int[] { i, j });
                    visit[i][j] = true;
                }
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        bfs();
    }
}
cs

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

boj 7576 토마토  (0) 2021.02.19
boj 17135 캐슬 디펜스  (0) 2021.02.17
boj 10026 적록색약  (0) 2021.02.13
boj 2206 벽 부수고 이동하기  (0) 2021.02.13
boj 14502 연구소  (0) 2021.02.12

www.acmicpc.net/problem/10026

 

10026번: 적록색약

적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다. 크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록)

www.acmicpc.net

적록색약이 아닌 사람이 봤을 때 구역의 갯수, 적록색약인 사람이 봤을 때 구역의 갯수를 순서대로 출력합니다.

적록색약이 아닌 사람 먼저 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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static boolean visit[][];
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static char list[][];
    static int N;
 
    static void bfs(int sx, int sy) {
        Queue<int[]> q = new LinkedList<>();
        q.add(new int[] { sx, sy });
        visit[sx][sy] = true;
        while (!q.isEmpty()) {
            int x = q.peek()[0];
            int y = q.poll()[1];
 
            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 >= N)
                    continue;
                if (visit[nx][ny] || list[x][y] != list[nx][ny])
                    continue;
 
                q.add(new int[] { nx, ny });
                visit[nx][ny] = true;
            }
        }
    }
 
    static void func() {
        int ansFirst = 0;
        int ansSecond = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (visit[i][j])
                    continue;
                bfs(i, j);
                ansFirst++;
            }
        }
 
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                visit[i][j] = false;
                if (list[i][j] == 'G')
                    list[i][j] = 'R';
            }
        }
 
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (visit[i][j])
                    continue;
                bfs(i, j);
                ansSecond++;
            }
        }
 
        System.out.println(ansFirst + " " + ansSecond);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        list = new char[N][N];
        visit = new boolean[N][N];
 
        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 17135 캐슬 디펜스  (0) 2021.02.17
boj 16236 아기 상어  (0) 2021.02.14
boj 2206 벽 부수고 이동하기  (0) 2021.02.13
boj 14502 연구소  (0) 2021.02.12
boj 20304 비밀번호 제작  (0) 2021.02.08

www.acmicpc.net/problem/2206

 

2206번: 벽 부수고 이동하기

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

www.acmicpc.net

(0, 0) ~ (N - 1, M - 1)까지 bfs로 순회하는데 벽을 한 개 까지 부수고 이동할 수 있습니다.

저는 visit배열을 3차원배열로 선언하여 (x, y, broke) => 벽을 broke번 부수고 x, y에 방문한 경우를 체크하였습니다.

벽을 이미 부순 경우에는 다음 벽을 부술 수 없고, 벽을 부수지 않은 경우에만 다음 벽을 부술 수 있습니다.

(N - 1, M - 1)에 도달하면 cnt값을 출력, 큐가 비어있음에도 도달하지 못하면 -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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Queue<int[]> q = new LinkedList<>();
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static boolean visit[][][];
    static char list[][];
    static int N, M, ans = -1;
 
    static void bfs() {
        q.add(new int[] { 0010 });
        visit[0][0][0= true;
        while (!q.isEmpty()) {
            int x = q.peek()[0];
            int y = q.peek()[1];
            int cnt = q.peek()[2];
            int broke = q.poll()[3];
 
            if (x == N - 1 && y == M - 1) {
                ans = cnt;
                break;
            }
 
            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] == '1' && broke == 1)
                    continue;
 
                if (list[nx][ny] == '1') {
                    if (visit[nx][ny][1])
                        continue;
                    q.add(new int[] { nx, ny, cnt + 11 });
                    visit[nx][ny][1= true;
                } else {
                    if (visit[nx][ny][broke])
                        continue;
                    q.add(new int[] { nx, ny, cnt + 1, broke });
                    visit[nx][ny][broke] = true;
                }
            }
        }
 
        System.out.println(ans);
    }
 
    static void input() throws Exception {
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        list = new char[N][];
        visit = new boolean[N][M][2];
 
        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();
        bfs();
    }
}
cs

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

boj 16236 아기 상어  (0) 2021.02.14
boj 10026 적록색약  (0) 2021.02.13
boj 14502 연구소  (0) 2021.02.12
boj 20304 비밀번호 제작  (0) 2021.02.08
boj 2606 바이러스  (0) 2021.02.03

www.acmicpc.net/problem/14502

 

14502번: 연구소

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크

www.acmicpc.net

연구소에 벽 3개를 설치하여 바이러스로부터 안전 영역의 크기를 최대로 해야합니다.

이 문제는 브루트포스 방식과 bfs를 사용하여 해결하였습니다.

 

브루트포스로 설치할 벽의 모든 경우를 구하였고, 3개의 벽을 설치하면 bfs를 돌려서 바이러스를 최대한 퍼뜨린 후에 안전 영역의 갯수를 구하였습니다.

 

 

[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
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
 
queue<pair<intint> > q;
int direct[4][2= { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };
bool visit[8][8];
int list[8][8];
int N, M, ans;
 
void bfs() {
    queue<pair<intint> > nq = q;
    int sum = 0;
    while (!nq.empty()) {
        int x = nq.front().first;
        int y = nq.front().second;
        nq.pop();
        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] != 0 || visit[nx][ny]) continue;
            visit[nx][ny] = true;
            nq.push({ nx,ny });
        }
    }
 
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (list[i][j] != 0 || visit[i][j]) continue;
            sum++;
        }
    }
 
    ans = max(ans, sum);
}
 
void func(int x, int y, int cnt) {
    if (cnt == 3) {
        bfs();
        memset(visit, falsesizeof(visit));
        return;
    }
 
    int sx = x;
    int sy = y;
    for (int i = sx; i < N; i++) {
        for (int j = sy; j < M; j++) {
            if (list[i][j] != 0continue;
 
            list[i][j] = 1;
            if (j == M - 1) func(i + 10, cnt + 1);
            else func(i, j + 1, cnt + 1);
            list[i][j] = 0;
        }
        sy = 0;
    }
}
 
void input() {
    cin >> N >> M;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> list[i][j];
 
            if (list[i][j] == 2) {
                q.push({ i,j });
                visit[i][j] = true;
            }
        }
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func(000);
    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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static int list[][] = new int[8][8];
    static Deque<int[]> virus = new ArrayDeque<>();
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static int N, M, ans;
 
    static void bfs() {
        Deque<int[]> dq = new ArrayDeque<>();
        boolean visit[][] = new boolean[8][8];
        dq.addAll(virus);
        Iterator<int[]> iter = dq.iterator();
        while (iter.hasNext()) {
            int xy[] = iter.next();
            visit[xy[0]][xy[1]] = 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 (nx < 0 || ny < 0 || nx >= N || ny >= M)
                    continue;
                if (visit[nx][ny] || list[nx][ny] == 1)
                    continue;
 
                dq.add(new int[] { nx, ny });
                visit[nx][ny] = true;
            }
        }
 
        int cnt = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (visit[i][j] || list[i][j] != 0)
                    continue;
 
                cnt++;
            }
        }
 
        ans = Math.max(ans, cnt);
    }
 
    static void func(int sx, int sy, int cnt) {
        if (cnt == 3) {
            bfs();
            return;
        }
 
        int i = sx;
        int j = sy;
        for (; i < N; i++) {
            for (; j < M; j++) {
                if (list[i][j] != 0)
                    continue;
 
                list[i][j] = 1;
                if (j == M - 1)
                    func(i + 10, cnt + 1);
                else
                    func(i, j + 1, cnt + 1);
                list[i][j] = 0;
            }
            j = 0;
        }
    }
 
    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());
                if (list[i][j] == 2) {
                    virus.add(new int[] { i, j });
                }
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        func(000);
        System.out.println(ans);
    }
}
cs

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

boj 10026 적록색약  (0) 2021.02.13
boj 2206 벽 부수고 이동하기  (0) 2021.02.13
boj 20304 비밀번호 제작  (0) 2021.02.08
boj 2606 바이러스  (0) 2021.02.03
boj 1012 유기농 배추  (0) 2021.02.03

www.acmicpc.net/problem/20304

 

20304번: 비밀번호 제작

서강대학교 전산실에서 보안직원으로 일하는 향빈이는 한 통의 이메일을 받게 되었다. 이메일에는 서버 관리자 계정에 대한 비정상적인 로그인 시도가 감지되었다는 내용이 적혀 있었고, 첨부

www.acmicpc.net

bfs에 비트마스킹까지 해야하는 문제입니다.

 

관리자 계정 비밀번호와 해커가 로그인 시도에 사용된 비밀번호의 안전거리로 계산한 안전도를 최대로 해야합니다.

우선 로그인 시도에 사용된 비밀번호가 관리자 계정 비밀번호와 같으면 안전거리는 0입니다. (고정)

이를 큐에 넣고 비트마스킹을 이용하여 bfs로 탐색을 합니다. 큐에는 번호와 안전도를 유지합니다.

 

이제 1부터 왼쪽시프트를 하면서 x와 &연산을 합니다. (y = x & i)

y > 0이면 같은 자릿수가 있다는 의미이며, x - i를 한 값이 거리가 1인 숫자입니다.

그리고 y == 0이면 같은 자릿수가 없다는 의미이며, x + i를 한 값이 거리가 1인 숫자입니다.

 

이 과정을 반복하여 cnt의 max를 구하여 출력합니다.

 

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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static Queue<int[]> q = new LinkedList<>();
    static int visit[];
    static int N, M, ans;
 
    static void bfs() {
        while (!q.isEmpty()) {
            int x = q.peek()[0];
            int cnt = q.poll()[1];
 
            ans = Math.max(ans, cnt);
            for (int i = 1; i <= N; i = i << 1) {
                int y = x & i;
 
                if (y > 0) {
                    if (visit[x - i] != -1)
                        continue;
                    q.add(new int[] { x - i, cnt + 1 });
                    visit[x - i] = cnt + 1;
                } else {
                    if (x + i > N || visit[x + i] != -1)
                        continue;
                    q.add(new int[] { x + i, cnt + 1 });
                    visit[x + i] = cnt + 1;
                }
            }
        }
 
        System.out.println(ans);
    }
 
    static void input() throws Exception {
        int x;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        visit = new int[N + 1];
        Arrays.fill(visit, -1);
 
        st = new StringTokenizer(br.readLine());
        M = Integer.parseInt(st.nextToken());
 
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < M; i++) {
            x = Integer.parseInt(st.nextToken());
            q.add(new int[] { x, 0 });
            visit[x] = 0;
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        bfs();
    }
}
cs

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

boj 2206 벽 부수고 이동하기  (0) 2021.02.13
boj 14502 연구소  (0) 2021.02.12
boj 2606 바이러스  (0) 2021.02.03
boj 1012 유기농 배추  (0) 2021.02.03
boj 16956 늑대와 양  (0) 2021.02.03

www.acmicpc.net/problem/2606

 

2606번: 바이러스

첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하이고 각 컴퓨터에는 1번 부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트워크 상에서 직접 연결되어 있는 컴퓨터 쌍의 수가 주어

www.acmicpc.net

처음에 1번 컴퓨터가 바이러스에 걸리고 이 컴퓨터로 인해 바이러스에 걸리는 컴퓨터가 몇 대인지 출력하는 문제입니다.

 

이 문제는 간단한 bfs로 해결할 수 있습니다.

입력으로 u와 v가 주어지면 둘이 연결되어있다는 말입니다.

이 그래프는 양방향 그래프이기 때문에 u의 간선에도 v를 추가하고, v의 간선에도 u를 추가해야합니다.

 

그 다음 1번부터 시작하여 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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static ArrayList<Integer> list[];
    static boolean visit[];
    static int N, M, ans;
 
    static void bfs() {
        Queue<Integer> q = new LinkedList<>();
        q.add(1);
        visit[1= true;
        while (!q.isEmpty()) {
            int v = q.peek();
 
            q.remove();
 
            for (int i = 0; i < list[v].size(); i++) {
                int next = list[v].get(i);
 
                if (visit[next])
                    continue;
 
                q.add(next);
                visit[next] = true;
                ans++;
            }
        }
    }
 
    static void input() throws Exception {
        int u, v;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        list = new ArrayList[N + 1];
        visit = new boolean[N + 1];
        for (int i = 1; i <= N; i++) {
            list[i] = new ArrayList<>();
        }
 
        st = new StringTokenizer(br.readLine());
        M = Integer.parseInt(st.nextToken());
 
        while (M-- > 0) {
            st = new StringTokenizer(br.readLine());
            u = Integer.parseInt(st.nextToken());
            v = Integer.parseInt(st.nextToken());
 
            list[u].add(v);
            list[v].add(u);
        }
    }
 
    public static void main(String[] args) throws Exception {
        input();
        bfs();
        System.out.println(ans);
    }
}
cs

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

boj 14502 연구소  (0) 2021.02.12
boj 20304 비밀번호 제작  (0) 2021.02.08
boj 1012 유기농 배추  (0) 2021.02.03
boj 16956 늑대와 양  (0) 2021.02.03
boj 20419 화살표 미로 (Easy)  (0) 2021.01.23

www.acmicpc.net/problem/1012

 

1012번: 유기농 배추

차세대 영농인 한나는 강원도 고랭지에서 유기농 배추를 재배하기로 하였다. 농약을 쓰지 않고 배추를 재배하려면 배추를 해충으로부터 보호하는 것이 중요하기 때문에, 한나는 해충 방지에 

www.acmicpc.net

배추영역 하나에 지렁이 한마리가 들어가고 최종적으로 배추밭에 필요한 지렁이의 수를 구하는 문제이며

탐색을 통해 배추영역의 갯수를 구하는 문제입니다.

 

저는 bfs를 사용했습니다.

입력으로 배추의 위치가 X, Y로 주어지면 list[X][Y] = 1로 표시합니다.

모든 입력을 다 받고 2중 for문을 돌려서 해당 칸이 1이면서 아직 방문하지 않은 위치면 그 위치를 시작으로 bfs를 돌립니다.

 

bfs로 현재 위치에서 주변에 1이 있는 좌표들을 큐에 넣고 중복체크를 해줍니다.

bfs 탐색이 종료되면 한 구역 탐색이 끝난 것이므로 ans를 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
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
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 boolean visit[][];
    static int direct[][] = { { 01 }, { 10 }, { 0-1 }, { -10 } };
    static int list[][];
    static int N, M, K, ans;
 
    static void print() {
        sb.append(ans + "\n");
        ans = 0;
    }
 
    static void bfs(int sx, int sy) {
        Queue<int[]> q = new LinkedList<>();
        q.add(new int[] { sx, sy });
        visit[sx][sy] = true;
        while (!q.isEmpty()) {
            int x = q.peek()[0];
            int y = q.peek()[1];
 
            q.remove();
 
            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] == 0)
                    continue;
 
                q.add(new int[] { nx, ny });
                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] == 1) {
                    if (visit[i][j])
                        continue;
 
                    bfs(i, j);
                    ans++;
                }
            }
        }
    }
 
    static void input() throws Exception {
        int u, v;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        list = new int[N][M];
        visit = new boolean[N][M];
 
        while (K-- > 0) {
            st = new StringTokenizer(br.readLine());
            u = Integer.parseInt(st.nextToken());
            v = Integer.parseInt(st.nextToken());
 
            list[u][v] = 1;
        }
    }
 
    public static void main(String[] args) throws Exception {
        st = new StringTokenizer(br.readLine());
        int tc = Integer.parseInt(st.nextToken());
        while (tc-- > 0) {
            input();
            func();
            print();
        }
        
        System.out.println(sb.toString());
    }
}
cs

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

boj 20304 비밀번호 제작  (0) 2021.02.08
boj 2606 바이러스  (0) 2021.02.03
boj 16956 늑대와 양  (0) 2021.02.03
boj 20419 화살표 미로 (Easy)  (0) 2021.01.23
boj 2638 치즈  (0) 2021.01.22

+ Recent posts