본문 바로가기

Archived(CSE Programming)/알고리즘(C++)

백준 14891_톱니바퀴

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

 

14891번: 톱니바퀴

첫째 줄에 1번 톱니바퀴의 상태, 둘째 줄에 2번 톱니바퀴의 상태, 셋째 줄에 3번 톱니바퀴의 상태, 넷째 줄에 4번 톱니바퀴의 상태가 주어진다. 상태는 8개의 정수로 이루어져 있고, 12시방향부터 시계방향 순서대로 주어진다. N극은 0, S극은 1로 나타나있다. 다섯째 줄에는 회전 횟수 K(1 ≤ K ≤ 100)가 주어진다. 다음 K개 줄에는 회전시킨 방법이 순서대로 주어진다. 각 방법은 두 개의 정수로 이루어져 있고, 첫 번째 정수는 회전시킨 톱니바퀴

www.acmicpc.net

해당 문제도 역시 시물레이션 문제였다. 그래서 상황을 코드로 옮기는 것에 주안을 해야하는데, 문제의 조건을 하나 잘못 이해한 것이 있어서 한참 헤맸다...

1(시계회전) 2(반시계회전) 3(회전X) 4(?)

다음과 같은 상황일 때, 나는 4번이 회전의 조건을 만족한다면 시계방향으로 회전하도록 해야하는 줄 알았다. 그런데, 3바로 옆의 톱니바퀴가 회전하지 않으면 당연히 회전하지 않는 것이 일반적인 상식인데 이를 간과해서 엄청나게 노가다를 했다.

 

1번이 회전할 경우 1->2->3->4

2번이 회전할 경우 2->1,3 -> 4 

...

 

이런식으로 노가다를 통해 200 라인 가까이 프로그래밍을 하였다. 

그러나, 3번이 회전하지 않는다면 그 오른쪽의 4번은 볼 필요도 없이 회전하지 않는다.

이 조건을 활용할 경우 로직은 굉장히 간단해진다.

주어진 번호의 톱니바퀴 바로 왼쪽(num-1) ~ 왼쪽 끝(0) 까지 회전체크
(만약 중간에 무회전 바퀴가 있으면 더 이상 왼쪽으로 진행하지 않아도 된다)

주어진 번호의 톱니바퀴 바로 오른쪽(num+1) ~ 오른쪽 끝(3) 까지 회전체크
(만약 중간에 무회전 바퀴가 있으면 더 이상 오른쪽으로 진행하지 않아도 된다)

다음의 로직을 통해 쉽게 해결이 가능하였다.

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;

// 시계 회전
void clock_circulate(int * a) {
	int temp = a[7];
	for (int i = 7; i > 0; i--)
		a[i] = a[i - 1];
	a[0] = temp;
}

// 반시계 회전
void unclock_circulate(int * a) {
	int temp = a[0];
	for (int i = 0; i < 7; i++)
		a[i] = a[i + 1];
	a[7] = temp;
}

// 회전
void circulate(int * a, int dir) {
	if (dir == 1)
		clock_circulate(a);
	else if (dir == -1)
		unclock_circulate(a);
	else
		return;
}

int main() {
	// N=0, S=1
	int wh[4][8];
	for (int i = 0; i < 4; i++) {
		string temp;
		cin >> temp;
		for (int j = 0; j < 8; j++)
			wh[i][j] = temp[j] - '0';
	}

	int n, num, dir;
	cin >> n;

	// main
	while (n--) {
		cin >> num >> dir;
		num--; // idx 0~3
		vector<int> d(4,0);
		d[num] = dir;

		// num 기준 왼쪽 기준
		for (int i = num - 1; i >= 0; i--) {
			if (wh[i][2] != wh[i + 1][6]) {
				d[i] = d[i + 1] * -1; // 반대방향
			}
			else
				break;
		}
		// num 기준 오른쪽 기준
		int rdir = dir;
		for (int i = num+1; i <=3; i++) {
			if (wh[i-1][2] != wh[i][6]) {
				d[i] = d[i - 1] * -1; // 반대방향
			}
			else
				break;
		}

		// 회전
		for (int i = 0; i < 4; i++) {
			circulate(wh[i], d[i]);
		}
	}

	// calculate
	int sum = 0;
	sum = wh[0][0] + wh[1][0] * 2 + wh[2][0] * 4 + wh[3][0] * 8;
	cout << sum;
}

'Archived(CSE Programming) > 알고리즘(C++)' 카테고리의 다른 글

백준 14890_경사로  (0) 2019.10.16
백준 14503_로봇 청소기  (0) 2019.10.16
백준 14499_주사위 굴리기  (0) 2019.10.15
프로그래머스_입국심사  (2) 2019.10.09
프로그래머스_섬 연결하기  (0) 2019.10.09