[백준] 14891번: 톱니바퀴

2022. 10. 10. 14:35TIL💡/Algorithms

https://www.acmicpc.net/problem/14891

 

14891번: 톱니바퀴

첫째 줄에 1번 톱니바퀴의 상태, 둘째 줄에 2번 톱니바퀴의 상태, 셋째 줄에 3번 톱니바퀴의 상태, 넷째 줄에 4번 톱니바퀴의 상태가 주어진다. 상태는 8개의 정수로 이루어져 있고, 12시방향부터

www.acmicpc.net

이번에도 구현(시뮬레이션) 어게인..

생각보다 구현 속도는 뚝딱뚝딱 빨라지고 있다.

그런데 눈이 이상한지, != 라고 써야하는 부분을 == 라고 쓰지 않나, second라고 써야하는 부분을 first라고 쓴 부분도 있었다..;;;

이런 경우 뭐 어쩔 수 없이 천천히 코드 한 줄씩 찍어보며 파악하는 수밖에 없다..

이번 문제는 어제 푼 주사위 문제와 유사하다.

대신 주사위에서는 주사위 면들의 값을 회전에 따라 옮겨주었으나, 이번에는 귀찮아서 그냥 톱니바퀴의 3시 방향, 9시 방향을 기준으로 포인터 삼아 포인터를 옮겨주는 방식으로 회전을 구현해주었다.

 

여기서 꿀팁은 회전 방향과 반대로 포인터를 옮겨준다는 아이디어를 가지면 좋다.

 

톱니바퀴가 만약 시계방향(+1)으로 회전한다면, 맞닿은 극의 위치는 고정되기 때문에 기존의 맞닿은 극의 이전 바큇살(-1)이 회전 후에 맞닿게 된다.

만약 이를 개념적으로 받아들이기 어렵다면, 예시로 하나만 그려보면 매우 쉽게 와닿는다.

이를 활용해 간단하게 함수로 만들었다.

void  _rotate(int wheel, int dir) {
	dirs[wheel].first = (dirs[wheel].first - dir + 8) % 8;
	dirs[wheel].second = (dirs[wheel].second - dir + 8) % 8;
}

이런 구현들은 그래도 이번엔 나름 빠르게 캐치했는데, 문제 구현 순서를 제대로 읽지 않아서 계속 원하는 결괏값이 나오지 않았다.

의도한 톱니바퀴를 우선 돌리고, 이에 대한 결과를 반영한 후 양옆의 톱니바퀴를 굴리는 줄 알았으나, 문제의 예시를 읽어보면 돌리기 이전의 값들을 바탕으로 양옆을 돌린 후 결과를 반영함을 알 수 있다.

 

그래서 문제 읽는 게 이렇게 중요하다...

 

그 부분을 고쳐주니 바로 통과되더라...ㅠ

 

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;
int K;
vector<vector<int>> wheels(4, vector<int>(8));
vector<pair<int,int>> dirs(4, {2, 6});

void  _rotate(int wheel, int dir) {
	dirs[wheel].first = (dirs[wheel].first - dir + 8) % 8;
	dirs[wheel].second = (dirs[wheel].second - dir + 8) % 8;
}

void rotate(int wheel, int dir, int start_dir) {
	// printf("%d 번째 바퀴의 3시 방향은 %d번째 바퀴입니다.\n", wheel + 1, dirs[wheel].first);
	if(wheel > 0 && start_dir <= 0){
		int left = dirs[wheel - 1].first;
		int right = dirs[wheel].second;

		if(wheels[wheel][right] != wheels[wheel - 1][left]) {
			rotate(wheel - 1, dir * -1, -1);
		}
	}

	if(wheel < 3 && start_dir >= 0) {
		int right = dirs[wheel + 1].second;
		int left = dirs[wheel].first;
		if(wheels[wheel + 1][right] != wheels[wheel][left]) {
			rotate(wheel + 1, dir * -1, 1);
		}
	}
	_rotate(wheel, dir);
}

void print_wheels(){
	for(int i = 0;i < 4;i++){
		for(int j = 0;j < 8;j++) {
			cout << wheels[i][j] << " ";
		}
		cout << endl;
	}
}

int main() {
	int cmd_cnt, answer = 0;
	string status;
	for(int i = 0;i < 4;i++){
		cin >> status;
		for(int j = 0;j < 8;j++) {
			wheels[i][j] = status[j] - '0';
		}
	}

	// print_wheels();


	cin >> cmd_cnt;
	for(int i = 0;i < cmd_cnt;i++) {
		int wheel, dir;
		cin >> wheel >> dir;
		// wheel 번째 바퀴를 dir 방향으로 돌린다.

		rotate(wheel - 1, dir, 0);
	}

	for(int i = 0; i <4;i++) {
		int dir_12 = (dirs[i].second + 2) % 8;
		if(wheels[i][dir_12] == 1) {
			answer += pow(2, i);
		}
	}

	cout << answer << '\n';

}