15684번 : 사다리 조작
문제)
사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선을 놓을 수 있는 위치의 개수는 H이고, 모든 세로선이 같은 위치를 갖는다. 아래 그림은 N = 5, H = 6 인 경우의 그림이고, 가로선은 없다.
![](https://blog.kakaocdn.net/dn/FRJnA/btspni9NdJV/qcHcQDI5GbYvqrRpjU8tK0/img.png)
초록선은 세로선을 나타내고, 초록선과 점선이 교차하는 점은 가로선을 놓을 수 있는 점이다. 가로선은 인접한 두 세로선을 연결해야 한다. 단, 두 가로선이 연속하거나 서로 접하면 안 된다. 또, 가로선은 점선 위에 있어야 한다.
![](https://blog.kakaocdn.net/dn/bkiKxf/btspkK0Mnfn/4xpLGNGFbrKuD79zcBH141/img.png)
위의 그림에는 가로선이 총 5개 있다. 가로선은 위의 그림과 같이 인접한 두 세로선을 연결해야 하고, 가로선을 놓을 수 있는 위치를 연결해야 한다.
사다리 게임은 각각의 세로선마다 게임을 진행하고, 세로선의 가장 위에서부터 아래 방향으로 내려가야 한다. 이때, 가로선을 만나면 가로선을 이용해 옆 세로선으로 이동한 다음, 이동한 세로선에서 아래 방향으로 이동해야 한다.
위의 그림에서 1번은 3번으로, 2번은 2번으로, 3번은 5번으로, 4번은 1번으로, 5번은 4번으로 도착하게 된다. 아래 두 그림은 1번과 2번이 어떻게 이동했는지 나타내는 그림이다.
![](https://blog.kakaocdn.net/dn/crFeVl/btspsFJ6XmO/Kr0Cxvk7AlKawxXl9CNKzk/img.png)
사다리에 가로선을 추가해서, 사다리 게임의 결과를 조작하려고 한다. 이때, i번 세로선의 결과가 i번이 나와야 한다. 그렇게 하기 위해서 추가해야 하는 가로선 개수의 최솟값을 구하는 프로그램을 작성하시오.
입력 :
첫째 줄에 세로선의 개수 N, 가로선의 개수 M, 세로선마다 가로선을 놓을 수 있는 위치의 개수 H가 주어진다. (2 ≤ N ≤ 10, 1 ≤ H ≤ 30, 0 ≤ M ≤ (N-1)×H)
둘째 줄부터 M개의 줄에는 가로선의 정보가 한 줄에 하나씩 주어진다.
가로선의 정보는 두 정수 a과 b로 나타낸다. (1 ≤ a ≤ H, 1 ≤ b ≤ N-1) b번 세로선과 b+1번 세로선을 a번 점선 위치에서 연결했다는 의미이다.
가장 위에 있는 점선의 번호는 1번이고, 아래로 내려갈 때마다 1이 증가한다. 세로선은 가장 왼쪽에 있는 것의 번호가 1번이고, 오른쪽으로 갈 때마다 1이 증가한다.
입력으로 주어지는 가로선이 서로 연속하는 경우는 없다.
출력 :
i번 세로선의 결과가 i번이 나오도록 사다리 게임을 조작하려면, 추가해야 하는 가로선 개수의 최솟값을 출력한다. 만약, 정답이 3보다 큰 값이면 -1을 출력한다. 또, 불가능한 경우에도 -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
|
#include <iostream>
#include <vector>
#include <algorithm>
#include <limits.h>
using namespace std;
int n, m, h;
int answer = INT_MAX;
vector<vector<int>> vec;
void recur(int x, int y, int cur);
bool check();
bool ladder(int start);
// 백트래킹 / 가로선을 추가해가면서 사다리 게임을 탐색하는 함수
void recur(int x, int y, int cur)
{
// 이미 구한 최솟값보다 크거나 같으면 탐색 중지
if (cur >= answer) return;
// 사다리 확인
if (check())
{
answer = min(answer, cur);
return;
}
// 최대 3개의 가로선
if (cur == 3) return;
// 가로선 추가를 시도하는 반복문
// 이미 확인했던 가로선은 확인하지 않음. (불필요한 탐색 줄임)
for (int i = x; i < h; i++)
{
for (int j = (i == x ? y : 1); j < n; j++)
{
if (vec[i][j - 1] || vec[i][j] || vec[i][j + 1]) continue;
vec[i][j] = 1;
recur(i, j + 2, cur + 1);
vec[i][j] = 0;
}
}
}
// 현재 사다리가 자기 자신으로 돌아올 수 있는지 확인하는 함수
bool check()
{
for (int i = 1; i < n + 1; i++)
{
if (!ladder(i))
{
return false;
}
}
return true;
}
// a로 시작한 사다리가 a로 끝났는지 확인
bool ladder(int start)
{
int temp = start;
int idx = 0;
while (idx != h)
{
if (vec[idx][start - 1])
{
idx++;
start--;
}
else if (vec[idx][start])
{
idx++;
start++;
}
else
{
idx++;
}
}
if (temp == start)
{
return true;
}
else
{
return false;
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> m >> h;
vec.resize(h, vector<int>(n + 1, 0));
int a, b;
for (int i = 0; i < m; i++)
{
cin >> a >> b;
vec[a - 1][b] = 1;
}
recur(0, 1, 0);
if (answer > 3)
{
cout << -1;
}
else
{
cout << answer;
}
return 0;
}
|
cs |
출처 : https://www.acmicpc.net/problem/15684
15684번: 사다리 조작
사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선을 놓을 수 있는 위치의 개수는 H이고, 모든 세로선
www.acmicpc.net
'Develop > 백준 (Cpp)' 카테고리의 다른 글
[백준] 14405번 : 피카츄 (C++) (0) | 2023.07.31 |
---|---|
[백준] 19942번 : 다이어트 (C++) (0) | 2023.07.30 |
[백준] 3197번 : 백조의 호수 (C++) (0) | 2023.07.30 |
[백준] 1189번 : 컴백홈 (C++) (0) | 2023.07.25 |
[백준] 14620번 : 꽃길 (C++) (0) | 2023.07.25 |