https://www.acmicpc.net/problem/12886
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
//a, b의 히스토리
bool visit[1501][1501];
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int a, b, c;
cin>>a>>b>>c;
int sum=a+b+c;
if(sum%3){
cout<<0;
return 0;
}
queue<pair<int, int>> q;
q.push(make_pair(a, b));
visit[a][b]=true;
while(!q.empty()){
int aa=q.front().first;
int bb=q.front().second;
if(aa==bb && aa==sum-aa-bb){
cout<<1;
return 0;
}
q.pop();
int stone[3]={aa, bb, sum-aa-bb};
sort(stone, stone+3);
//(0, 1), (1, 2), (0, 2) 비교
for(int i=0;i<3;i++){
int first;
int second;
switch(i){
case 0: //0, 1
first=stone[0]*2;
second=stone[1]-stone[0];
break;
case 1: //1, 2
first=stone[0];
second=stone[1]*2;
break;
case 2: //0, 2
first=stone[0]*2;
second=stone[1];
break;
}
if(!visit[first][second]){
visit[first][second]=true;
q.push(make_pair(first, second));
}
}
}
cout<<0;
return 0;
}
1. 문제
오늘 강호는 돌을 이용해 재미있는 게임을 하려고 한다. 먼저, 돌은 세 개의 그룹으로 나누어져 있으며 각각의 그룹에는 돌이 A, B, C개가 있다. 강호는 모든 그룹에 있는 돌의 개수를 같게 만들려고 한다.
강호는 돌을 단계별로 움직이며, 각 단계는 다음과 같이 이루어져 있다.
크기가 같지 않은 두 그룹을 고른다. 그 다음, 돌의 개수가 작은 쪽을 X, 큰 쪽을 Y라고 정한다. 그 다음, X에 있는 돌의 개수를 X+X개로, Y에 있는 돌의 개수를 Y-X개로 만든다.
A, B, C가 주어졌을 때, 강호가 돌을 같은 개수로 만들 수 있으면 1을, 아니면 0을 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 A, B, C가 주어진다. (1 ≤ A, B, C ≤ 500)
출력
돌을 같은 개수로 만들 수 있으면 1을, 아니면 0을 출력한다.
2. 풀이
int a, b, c;
cin>>a>>b>>c;
int sum=a+b+c;
if(sum%3){
cout<<0;
return 0;
}
돌의 개수는 0 이상의 정수이므로 3으로 나누어 떨어지지 않는다면 세 돌을 같게 만들 수 없다.
//a, b의 히스토리
bool visit[1501][1501];
queue<pair<int, int>> q;
q.push(make_pair(a, b));
visit[a][b]=true;
visit[i][j]: 세 돌 중 두 개의 돌이 i, j의 개수일 때를 방문했는 지 이다. 연산은 3개 중 두 개의 돌을 골라 작은 돌을 두배 하고, 작은 돌의 수 만큼 큰 돌에서 빼므로 전체 돌의 개수는 항상 같다. 따라서 총 돌의 개수에서 a, b를 뺀 값이 나머지 c의 값이다.
int aa=q.front().first;
int bb=q.front().second;
if(aa==bb && aa==sum-aa-bb){
cout<<1;
return 0;
}
세 돌의 개수가 같다면 1을 출력하고 프로그램을 종료한다.
int stone[3]={aa, bb, sum-aa-bb};
sort(stone, stone+3);
//(0, 1), (1, 2), (0, 2) 비교
for(int i=0;i<3;i++){
int first;
int second;
switch(i){
case 0: //0, 1
first=stone[0]*2;
second=stone[1]-stone[0];
break;
case 1: //1, 2
first=stone[0];
second=stone[1]*2;
break;
case 2: //0, 2
first=stone[0]*2;
second=stone[1];
break;
}
if(!visit[first][second]){
visit[first][second]=true;
q.push(make_pair(first, second));
}
}
세 돌의 개수를 저장하고, 크기에 따른 연산 방법이 다르므로 돌의 개수를 정렬해준다. 그렇게 되면 아래 3가지 케이스의 연산을 할 수 있다.
- 0번째 돌과 1번째 돌: 0번째 돌에 두 배를 하고, 1번째 돌에서 0번째 돌을 뺀다.
- 1번째 돌과 2번째 돌: 0번째 돌은 연산에 관여하지 않는다. 1번째 돌에 2배를 하면 2번째 돌은 자동으로 결정이 된다.
- 0번째 돌과 2번째 돌: 0번째 돌에 두 배를 하고, 1번째 돌은 연산하지 않는다. 2번째 돌의 개수는 자동으로 결정된다.
연산이 끝나고 해당 케이스를 방문한 적이 있는지 확인하여 BFS를 돌린다. 다 돌았음에도 세 돌의 개수가 같은 케이스가 존재하지 않았다면 0을 출력하고 프로그램을 종료한다.
'Coding Test' 카테고리의 다른 글
| 백준 16973 직사각형 탈출 (Java) (2) | 2024.10.03 |
|---|---|
| 백준 1963 소수 경로 (Java) (1) | 2024.10.02 |
| 백준 9019 DSLR (C++) (0) | 2024.09.26 |
| 백준 21923 곡예 비행 (C++) (0) | 2024.09.23 |
| 백준 2073 수도배관공 (C++) (1) | 2024.09.22 |