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/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

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

+ Recent posts