- 문제
사다리 게임은 N개의 세로선과 M개의 가로선으로 이루어져 있다. 인접한 세로선 사이에는 가로선을 놓을 수 있는데, 각각의 세로선마다 가로선을 놓을 수 있는 위치의 개수는 H이고, 모든 세로선이 같은 위치를 갖는다. 아래 그림은 N = 5, H = 6 인 경우의 그림이고, 가로선은 없다.
초록선은 세로선을 나타내고, 초록선과 점선이 교차하는 점은 가로선을 놓을 수 있는 점이다. 가로선은 인접한 두 세로선을 연결해야 한다. 단, 두 가로선이 연속하거나 서로 접하면 안 된다. 또, 가로선은 점선 위에 있어야 한다.
위의 그림에는 가로선이 총 5개 있다. 가로선은 위의 그림과 같이 인접한 두 세로선을 연결해야 하고, 가로선을 놓을 수 있는 위치를 연결해야 한다.
사다리 게임은 각각의 세로선마다 게임을 진행하고, 세로선의 가장 위에서부터 아래 방향으로 내려가야 한다. 이때, 가로선을 만나면 가로선을 이용해 옆 세로선으로 이동한 다음, 이동한 세로선에서 아래 방향으로 이동해야 한다.
위의 그림에서 1번은 3번으로, 2번은 2번으로, 3번은 5번으로, 4번은 1번으로, 5번은 4번으로 도착하게 된다. 아래 두 그림은 1번과 2번이 어떻게 이동했는지 나타내는 그림이다.
1번 세로선 | 2번 세로선 |
사다리에 가로선을 추가해서, 사다리 게임의 결과를 조작하려고 한다. 이때, 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을 출력한다.
- 예제 입력
2 0 3
2 1 3
1 1
5 5 6
1 1
3 2
2 3
5 1
5 4
6 5 6
1 1
3 2
1 3
2 5
5 5
5 8 6
1 1
2 2
3 3
4 4
3 1
4 2
5 3
6 4
5 12 6
1 1
1 3
2 2
2 4
3 1
3 3
4 2
4 4
5 1
5 3
6 2
6 4
5 6 6
1 1
3 1
5 2
4 3
2 3
1 4
- 예제 출력
0
1
3
3
-1
-1
2
- 접근방식
범위가 2<=N<=10, 1<=H<=30 이고 추가 되는 가로선의 개수가 3개가 넘으면 안되기 때문에 300C3이 최대값이다.
상태값을 저장하는 visited 필요, i번째 세로선의 결과가 i번인지 체크하는 함수 필요
- 코드
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int n, m, h, a, b, visited[34][34], result = 9999999;
bool itoi_check()
{
for (int i = 1; i <= n; i++)
{
int start = i;
for (int j = 1; j <= h; j++)
{
if (visited[j][start]) start++; //선을 오른쪽에 존재
else if (visited[j][start - 1]) start--; // 선을 왼쪽에 존재
}
if (start != i) return false;
}
return true;
}
void line(int here, int cnt)
{
if (cnt > 3 || cnt >= result) return;
if (itoi_check())
{
result = min(result, cnt);
return;
}
for (int i = here; i <= h; i++)
{
for (int j = 1; j <= n; j++)
{
if (visited[i][j] || visited[i][j - 1] || visited[i][j + 1]) continue; // 선을 그려야 하는 부분에 선이 존재하면 그리지 않음
visited[i][j] = 1;
line(i, cnt + 1);
visited[i][j] = 0;
}
}
}
int main()
{
cin >> n >> m >> h;
for (int i = 0; i < m; i++)
{
cin >> a >> b;
visited[a][b] = 1;
}
line(1, 0);
cout << ((result == 9999999) ? -1 : result);
return 0;
}
'C++ > BOJ' 카테고리의 다른 글
[C++]/백준 1189번 컴백홈 (0) | 2024.03.05 |
---|---|
[C++]/백준 14620번 꽃길 (1) | 2024.03.05 |
[C++]/백준 9934번 완전 이진 트리 (0) | 2024.03.05 |
[C++]/백준 2529번 부등호 (0) | 2024.03.05 |
[C++]/백준 1052번 물병 (1) | 2024.03.04 |