본문 바로가기
백준

백준 2931 가스관

by 콩순이냉장고 2021. 4. 5.

문제 URL : www.acmicpc.net/problem/2931

 

2931번: 가스관

러시아 가스를 크로아티아로 운반하기 위해 자그레브와 모스코바는 파이프라인을 디자인하고 있다. 두 사람은 실제 디자인을 하기 전에 파이프 매니아 게임을 이용해서 설계를 해보려고 한다.

www.acmicpc.net

 

문제접근법 :  전수조사를 통해 해결했습니다. 

어떻게 전수 조사를 했냐면 board[i][j]== '.' 일경우 "|-1234+"를 넣어서 조사합니다.

그러나 여기서 순서가 중요한데 +를 제외한 나머지는 순서는 상관없지만 +를 넣는경우는 항상 나중에 합니다.

왜냐하면 | 를 넣어서 해결할수있는걸 +를 넣어서도 해결할수있기때문에 순서가 중요합니다.

 

또한 파이프가 +모양인곳은 반드시 2번 거처가기때문에 몇번을 거첬는지 확인하는것도 중요합니다.

또한 도착지점의 파이프를 + 로 생각해야 어떤 지점이든 바로 들어올수가있습니다. 그러나 도착지점은 1번만 거치기때문에 헷갈리시면 안됩니다.

 

소스코드 : 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//By 콩순이냉장고
#include <string>
#include<cstdio>
#include <unordered_set>
#include <iostream>
#include <vector>
using namespace std;
int idx[255];
int n, m;
char board[30][30];
int sy, sx;
string p = "|-1234+"//+는 늘 나중에탐색하기위해
int cnt;
int pipe[7][4= { //파이프 모양
    {1,0,1,0},
    {0,1,0,1},
    {0,1,1,0},
    {1,1,0,0},
    {1,0,0,1},
    {0,0,1,1},
    {1,1,1,1}
};
int dy[4= { -1,0,1,0 };
int dx[4= { 0,1,0,-1 };
int dir[7][4= { //파이프마다 들어올때 나가는방향을 저장해줌
    {2,-1,0,-1},
    {-1,3,-1,1},
    {-1,2,1,-1},
    {1,0,-1,-1},
    {3,-1,-1,0},
    {-1,-1,3,2},
    {2,3,0,1}
};
bool isrange(int y, int x) {
    return 1 <= y && y <= n && 1 <= x && x <= m;
}
void input() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++) {
            cin >> board[i][j];
            if (board[i][j] == 'M') {
                sy = i;
                sx = j;
            }
            if (board[i][j] != '.') {
                if (board[i][j] == '+')//밟아야할땅이 2번
                    cnt += 2;
                else//그외는 한번
                    cnt++;
            }
        }
    }
}
void init() {
    
    for (int i = 0; i < p.size(); i++)
        idx[p[i]] = i;
    idx['Z'= 6;
    idx['M'= 6;
}
void backtrack(int y, int x,int d,bool &flag,int walk=1) {
    if (board[y][x] == 'Z') {
        if(walk==cnt)//밟은땅이 cnt라면 도착
            flag = true;
        return;
    }
    int ny = y + dy[d];
    int nx = x + dx[d];
    int ntunnel = idx[board[ny][nx]];
    if (isrange(ny, nx) && board[ny][nx] != '.') {
        if (pipe[ntunnel][(d+2)%4]&&dir[ntunnel][(d+2)%4]>=0) {//다음 파이프터널을 통해 들어갈수있고 방향이 올바르다면
            backtrack(ny, nx, dir[ntunnel][(d + 2) % 4], flag,walk+1);//다음 방향 dir[ntunnel][(d+2)%4] 이게 가장중요
        }
    }
 
}
 
void solve() {
 
    bool flag = false;
    init();
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++) {
            if (board[i][j] == '.') {
                for (int k = 0; k < 7; k++) {
                    board[i][j] = p[k];
                    if (k == 6)//+파이프라면 2번밟아야함
                        cnt += 2;
                    else //그외는 한번
                        cnt++;
                    for (int d = 0; d < 4; d++) {
                        backtrack(sy, sx,d, flag);
                        if (flag) {
                            cout << i << " " << j << " " << board[i][j] << "\n";
                            return;
                        }
                    }
 
                    //원상복구
                    if (k == 6)
                        cnt -= 2;
                    else
                        cnt--;
 
                }
                board[i][j] = '.';
            }
        }
    }
 
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    input();
    solve();
 
}
 
cs

 

논리적인 오류 혹은 더좋은 아이디어

궁금한점 혹은 모르는점 이있다면 언제든지 댓글을 이용해주시면 감사합니당

 

'백준' 카테고리의 다른 글

백준 17130 토끼가 정보섬에 올라온 이유  (0) 2021.04.16
백준 1600 말이 되고픈 원숭이  (0) 2021.04.05
백준 14888 연산자 끼워넣기  (0) 2021.02.17
백준 14502 연구소  (0) 2021.02.17
백준 2568 전깃줄 - 2  (0) 2021.02.15