



https://www.acmicpc.net/problem/14891
14891번: 톱니바퀴
첫째 줄에 1번 톱니바퀴의 상태, 둘째 줄에 2번 톱니바퀴의 상태, 셋째 줄에 3번 톱니바퀴의 상태, 넷째 줄에 4번 톱니바퀴의 상태가 주어진다. 상태는 8개의 정수로 이루어져 있고, 12시방향부터
www.acmicpc.net
구현/시뮬레이션 문제이다.
여기서 중요한 것은 톱니바퀴가 순차적으로 움직이는 것이 아닌 일괄적으로 움직인다는 것이다.
이것 때문에 참 힘들었지만 내 이해력이 부족했던 거겠죵
첫 번째로는 4개의 톱니바퀴를 구조체 배열로 만들어주었다.
struct tobni {
deque<int> wheel;
};
struct tobni tobni[5];
deque는 앞/뒤로 push와 pop이 가능한 container이다.
배열로 회전을 구현하기에는 시간이 오래 걸릴 것 같아서 deque를 사용하였다.
참고로 index가 1인 톱니바퀴는 사용하지 않을 거라 5 크기로 선언해주었다.
그리고 방향에 따른 회전 함수를 만들어주었다.
void turn(struct tobni& tobni, int dir) {
if (dir == 1) {
// 시계 방향이라면
int tmp = tobni.wheel.back();
tobni.wheel.push_front(tmp);
tobni.wheel.pop_back();
}
else if (dir == -1) {
// 반시계 방향이면
int tmp = tobni.wheel.front();
tobni.wheel.push_back(tmp);
tobni.wheel.pop_front();
}
// dir = 0 : 회전 X
}
참조형 변수로 원래 구조체에 있는 wheel deque가 변할 수 있게 하였다.


참고로 turn 함수는 위와 같은 흐름으로 굴러간다.
시계 방향이면 맨 뒤에 있는 원소, 반시계 방향이면 맨 앞에 있는 원소를 pop하여
시계 방향이면 맨 앞으로, 반시계 방향이면 맨 뒤로 붙여준다.
이제 제일 중요한 것은 회전을 각각 독립적으로 한다는 것이다.
하지만 1번 톱니바퀴 기준으로 2번 톱니바퀴가 회전하지 않았다면 3번, 4번도 회전하면 안된다는 조건만 만족해주면 된다.
for (int i = 0; i < K; i++)
{
int num, dir;
cin >> num >> dir; // 번호, 방향 입력받음
for (int i = 0; i < 5; i++) { dirr[i] = 0; } // 방향 초기화
dirr[num] = dir; // 돌리려는 톱니바퀴 미리 설정
if (num == 1) { // 1번
for (int j = 1; j <= 3; j++) { // 3번 -> 2번 -> 1번 톱니바퀴 순으로 검사
if (tobni[j].wheel.at(2) != tobni[j + 1].wheel.at(6))
dirr[j + 1] = (dirr[j] == 1) ? -1 : 1;
else break;
}
}
else if (num == 2) { // 2번
// 왼쪽
if (tobni[num - 1].wheel.at(2) != tobni[num].wheel.at(6)) {
// 1번 톱니바퀴 검사
dirr[num - 1] = (dirr[num] == 1) ? -1 : 1;
}
// 오른쪽
for (int j = 2; j <= 3; j++) { // 3번 -> 4번 톱니바퀴 순으로 검사
if (tobni[j].wheel.at(2) != tobni[j + 1].wheel.at(6))
dirr[j + 1] = (dirr[j] == 1) ? -1 : 1;
else break;
}
}
else if (num == 3) { // 3번
// 오른쪽
if (tobni[num].wheel.at(2) != tobni[num + 1].wheel.at(6)) {
// 4번 톱니바퀴 검사
dirr[num + 1] = (dirr[num] == 1) ? -1 : 1;
}
// 왼쪽
for (int j = 3; j >= 2; j--) { // 2번 -> 1번 톱니바퀴 순으로 검사
if (tobni[j - 1].wheel.at(2) != tobni[j].wheel.at(6))
dirr[j - 1] = (dirr[j] == 1) ? -1 : 1;
else break;
}
}
else { // 4번
for (int j = 4; j >= 2; j--) { // 3번 -> 2번 -> 1번 톱니바퀴 순으로 검사
if (tobni[j-1].wheel.at(2) != tobni[j].wheel.at(6))
dirr[j - 1] = (dirr[j] == 1) ? -1 : 1;
else break;
}
}
for (int j = 1; j <= 4; j++) turn(tobni[j], dirr[j]); // 일괄 회전
}
이게 핵심이다!
전체 코드는 아래와 같다.
#include <iostream>
#include <deque>
#include <cmath>
using namespace std;
struct tobni {
deque<int> wheel;
};
struct tobni tobni[5];
int K;
// 독립적으로 회전시켜라
void turn(struct tobni& tobni, int dir) {
if (dir == 1) {
// 시계 방향이라면
int tmp = tobni.wheel.back();
tobni.wheel.push_front(tmp);
tobni.wheel.pop_back();
}
else if (dir == -1) {
// 반시계 방향이면
int tmp = tobni.wheel.front();
tobni.wheel.push_back(tmp);
tobni.wheel.pop_front();
}
// dir = 0 : 회전 X
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
for (int i = 1; i <= 4; i++)
{
string x;
cin >> x;
for (int j = 0; j < 8; j++) {
tobni[i].wheel.push_back(x[j] - '0'); // ascii 코드 참고
}
}
cin >> K;
int dirr[5];
for (int i = 0; i < K; i++)
{
int num, dir;
cin >> num >> dir; // 번호, 방향 입력받음
for (int i = 0; i < 5; i++) { dirr[i] = 0; } // 방향 초기화
dirr[num] = dir; // 돌리려는 톱니바퀴 미리 설정
if (num == 1) { // 1번
for (int j = 1; j <= 3; j++) { // 3번 -> 2번 -> 1번 톱니바퀴 순으로 검사
if (tobni[j].wheel.at(2) != tobni[j + 1].wheel.at(6))
dirr[j + 1] = (dirr[j] == 1) ? -1 : 1;
else break;
}
}
else if (num == 2) { // 2번
// 왼쪽
if (tobni[num - 1].wheel.at(2) != tobni[num].wheel.at(6)) {
// 1번 톱니바퀴 검사
dirr[num - 1] = (dirr[num] == 1) ? -1 : 1;
}
// 오른쪽
for (int j = 2; j <= 3; j++) { // 3번 -> 4번 톱니바퀴 순으로 검사
if (tobni[j].wheel.at(2) != tobni[j + 1].wheel.at(6))
dirr[j + 1] = (dirr[j] == 1) ? -1 : 1;
else break;
}
}
else if (num == 3) { // 3번
// 오른쪽
if (tobni[num].wheel.at(2) != tobni[num + 1].wheel.at(6)) {
// 4번 톱니바퀴 검사
dirr[num + 1] = (dirr[num] == 1) ? -1 : 1;
}
// 왼쪽
for (int j = 3; j >= 2; j--) { // 2번 -> 1번 톱니바퀴 순으로 검사
if (tobni[j - 1].wheel.at(2) != tobni[j].wheel.at(6))
dirr[j - 1] = (dirr[j] == 1) ? -1 : 1;
else break;
}
}
else { // 4번
for (int j = 4; j >= 2; j--) { // 3번 -> 2번 -> 1번 톱니바퀴 순으로 검사
if (tobni[j-1].wheel.at(2) != tobni[j].wheel.at(6))
dirr[j - 1] = (dirr[j] == 1) ? -1 : 1;
else break;
}
}
for (int j = 1; j <= 4; j++) turn(tobni[j], dirr[j]); // 일괄 회전
}
int sum = 0;
for (int i = 1; i <= 4; i++) {
sum += tobni[i].wheel.at(0) * pow(2, i - 1);
}
cout << sum;
}

'백준' 카테고리의 다른 글
[15686] 치킨 배달 (0) | 2023.04.10 |
---|---|
[14503] 로봇 청소기 (0) | 2023.04.07 |
[13458] 시험 감독 (0) | 2023.04.06 |
[14501] 퇴사 (0) | 2023.04.05 |
[11444] 피보나치 수 6 (0) | 2023.02.08 |
댓글