본문 바로가기
백준

[14891] 톱니바퀴

by kmyobin 2023. 4. 8.


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

댓글