[백준 12886] 돌 그룹 (C#, C++) - soo:bak
작성일 :
문제 링크
설명
세 개의 돌 그룹에서 돌의 개수를 같게 만들 수 있는지 확인하는 문제입니다.
각 단계에서 크기가 다른 두 그룹을 선택하고, 돌의 개수가 적은 그룹 X
와 많은 그룹 Y
를 선택하여,
X
그룹의 돌을 X + X
로 늘리고, Y
그룹의 돌을 Y-X
로 줄이는 작업을 반복하고,
이 과정에서 세 그룹의 돌 수가 모두 같아지는 경우를 탐색해야 합니다.
우선, 세 그룹의 돌의 총합이 3
으로 나누어 떨이지지 않는 경우, 세 그룹의 돌의 수를 같도록 만들 수는 없으므로,
총 합이 3
의 배수가 아니면, 바로 0
을 출력합니다.
이후, 시작 상태에서 BFS
알고리듬을 통해 가능한 모든 돌의 이동을 시도하며 탐색을 진행합니다.
각 상태에서는 세 그룹 중에서 ‘서로 다른 두 그룹’ 을 선택하여 돌을 이동하며,
새로운 상태가 이미 이전에 방문했던 상태가 아닌 경우에 BFS
의 큐에 추가합니다.
BFS
과정 중 세 그룹의 돌 수가 모두 같아지면, 1
을 반환하며 종료합니다.
만약, BFS
과정이 모두 종료되었음에도 세 그룹의 돌 수가 모두 같아지는 경우를 탐색하지 못하였다면 0
을 반환합니다.
Code
[ 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
namespace Solution {
class Program {
private const int END = 1_001;
private static bool[,] isVisited = new bool[END, END];
static int BFS(int a, int b, int sum) {
var queue = new Queue<(int, int)>();
queue.Enqueue((a, b));
isVisited[a, b] = true;
while (queue.Count > 0) {
var (curA, curB) = queue.Dequeue();
var curC = sum - curA - curB;
if (new[] {curA, curB, curC}.All(x => x == curA))
return 1;
var pairs = new[] {
(curA, curB), (curA, curC), (curB, curC)
};
foreach (var (first, second) in pairs) {
var nextA = first;
var nextB = second;
if (nextA < nextB) {
nextB -= nextA;
nextA *= 2;
} else if (nextA > nextB) {
nextA -= nextB;
nextB *= 2;
} else continue ;
var nextC = sum - nextA - nextB;
var sorted = new[] { nextA, nextB, nextC }.OrderBy(x => x).ToArray();
var minVal = sorted[0];
var maxVal = sorted[2];
if (minVal >= 0 && maxVal < END) {
if (!isVisited[minVal, maxVal]) {
isVisited[minVal, maxVal] = true;
queue.Enqueue((minVal, maxVal));
}
}
}
}
return 0;
}
static void Main(string[] args) {
Console.SetIn(new StreamReader(Console.OpenStandardInput()));
var inputs = Console.ReadLine()!.Split(' ').Select(int.Parse).ToArray();
var a = inputs[0];
var b = inputs[1];
var c = inputs[2];
var sum = a + b + c;
Console.WriteLine(sum % 3 != 0 ? 0 : BFS(a, b, sum));
}
}
}
[ 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
#include <bits/stdc++.h>
#define END 1001
using namespace std;
typedef pair<int, int> pii;
bool isVisited[END][END];
int bfs(int a, int b, int sum) {
queue<pii> q;
q.push({a, b});
isVisited[a][b] = true;
while (!q.empty()) {
int curA = q.front().first,
curB = q.front().second,
curC = sum - curA - curB;
q.pop();
if (curA == curB && curA == curC)
return 1;
int combX[3] = {curA, curA, curB},
combY[3] = {curB, curC, curC};
for (int i = 0; i < 3; i++) {
int nextA = combX[i],
nextB = combY[i];
if (nextA < nextB) {
nextB -= nextA;
nextA *= 2;
} else if (nextA > nextB) {
nextA -= nextB;
nextB *= 2;
} else continue ;
int nextC = sum - nextA - nextB,
minVal = min({nextA, nextB, nextC}),
maxVal = max({nextA, nextB, nextC});
if (minVal >= 0 && minVal < END) {
if (!isVisited[minVal][maxVal]) {
isVisited[minVal][maxVal] = true;
q.push({minVal, maxVal});
}
}
}
}
return 0;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int a, b, c; cin >> a >> b >> c;
int sum = a + b + c;
if (sum % 3) cout << 0 << "\n";
else cout << bfs(a, b, sum) << "\n";
return 0;
}