백준 16197 두 동전
본문 바로가기
알고리즘 모음집/알고리즘 (Algorithm)

백준 16197 두 동전

by KyeongMin 2019. 9. 8.
728x90
반응형

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

 

16197번: 두 동전

N×M 크기의 보드와 4개의 버튼으로 이루어진 게임이 있다. 보드는 1×1크기의 정사각형 칸으로 나누어져 있고, 각각의 칸은 비어있거나, 벽이다. 두 개의 빈 칸에는 동전이 하나씩 놓여져 있고, 두 동전의 위치는 다르다. 버튼은 "왼쪽", "오른쪽", "위", "아래"와 같이 4가지가 있다. 버튼을 누르면 두 동전이 버튼에 쓰여 있는 방향으로 동시에 이동하게 된다. 동전이 이동하려는 칸이 벽이면, 동전은 이동하지 않는다. 동전이 이동하려는 방향에 칸이 없

www.acmicpc.net

 

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
#include<stdio.h>
#include<queue>
#include<algorithm> 
#include<iostream>
#define NSIZE 21
#define MSIZE 21
using namespace std;
char input[NSIZE][MSIZE];
int N, M;
int chk[NSIZE][MSIZE][NSIZE][MSIZE];
int dy[] = { 0,0,-1,1 };
int dx[] = { -1,1,0,0 };
struct Data {
    int y, x, y1, x1, cnt;
};
queue<Data>q;
void init() {
    int y, x, y1, x1;
    scanf("%d %d"&N, &M);
    int cnt = 0;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            cin >> input[i][j];
            if (input[i][j] == 'o' && cnt == 0) {
                cnt++;
                y = i; x = j;
                input[i][j] = '.';
            }
            else if (input[i][j] == 'o' && cnt == 1) {
                y1 = i; x1 = j;
                input[i][j] = '.';
            }
        }
    }
 
    q.push({ y,x,y1,x1,0 });
    chk[y][x][y1][x1] = 1;
}
int Min = 0x7fffffff;
void bfs() {
 
    while (!q.empty()) {
        Data c = q.front(); q.pop();
        if (c.cnt > 10) {
            return;
        }
        int cnt = 0;
        if (c.y == 0 || c.y == N + 1 || c.x == 0 || c.x == M + 1) {
            cnt++;
        }
        if (c.y1 == 0 || c.y1 == N + 1 || c.x1 == 0 || c.x1 == M + 1) {
            cnt++;
        }
        if (cnt == 1) {
            if (Min > c.cnt) {
                Min = c.cnt;
            }
            return;
        }
        if (cnt == 2)continue;
        for (int dir = 0; dir < 4; dir++) {
            Data n = c;
            n.y += dy[dir];
            n.x += dx[dir];
            n.y1 += dy[dir];
            n.x1 += dx[dir];
            n.cnt++;
 
 
 
            if (input[n.y][n.x] != '#' && input[n.y1][n.x1] != '#') {//벽이면 원위치
                if (chk[n.y][n.x][n.y1][n.x1] == 0) {
                    chk[n.y][n.x][n.y1][n.x1] = 1;
                    q.push(n);
                }
            }
            //chk[n.y][n.x][n.y1][n.x1] == 0 &&
            if (input[n.y][n.x] == '#' && input[n.y1][n.x1] != '#') {//벽이면 원위치
                n.y = c.y; n.x = c.x;
                if (chk[n.y][n.x][n.y1][n.x1] == 0) {
                    chk[n.y][n.x][n.y1][n.x1] = 1;
                    q.push(n);
                }
            }
            if (input[n.y][n.x] != '#' && input[n.y1][n.x1] == '#') {//벽이면 원위치
                n.y1 = c.y1; n.x1 = c.x1;
                if (chk[n.y][n.x][n.y1][n.x1] == 0) {
                    chk[n.y][n.x][n.y1][n.x1] = 1;
                    q.push(n);
                }
            }
        }
    }
}
int main(void) {
 
    init();
    bfs();
    if (Min == 0x7fffffff)Min = -1;
    printf("%d", Min);
    return 0;
}
 
 




단순한 bfs이긴 한데 조금 조건이 들어간 탐색 문제 입니다 주의 할점은 동전이 이동하는 조건 인데
두동전이 한번에 움직이기 때문에
저는 세가지로 조건을 주었습니다
1번 동전과 2번 동전이 있다고 하면
두동전이 이동하는 위치에 벽이 아닌경우

1번 동전이 이동하는 위치에 벽이 있고
2번 동번이 이동하은 위치에 벽이 없고

그반대인 경우를 적어놓고 설계를 했고

0,0 부터 입력을 받게 되면 범위의 벗어난값이 -1가 되는게 있어 혹시나 해서 1,1부터 N, M 까지 받고
0,0이나 N+1, M+1 가되는 동전이 두개가 아니고 한개인경우에 값을 저장하고 리턴하는 식으로 구현했습니다

소스에 굳이 넣을필요없는 게 있긴하지만 참고 하고 봐주세요

오늘은 여기까지이고 즐거운 코딩 하세요

 

728x90
반응형

댓글