-
[백준 14891] 톱니바퀴C 프로그래밍/BOJ 2022. 10. 3. 14:58728x90
https://www.acmicpc.net/problem/14891
#include <cstdio> #include <queue> char in_data[4 + 2][8 + 2]; int topni[4 + 2][8 + 2]; // 숫자로 변경해서 운영 // N극이면 0, S극이면 1 int K; int score[2][4] = { {0, 0, 0, 0}, // 12시 방향이 N극일때 {1, 2, 4, 8} // S극일때 점수판 }; struct _st { int n; // 몇번째 톱니바퀴가 int d; // 어떤 방향으로 회전할 것인지 // -1 반시계, 1 시계 int flag; // 한번 연쇄 일어나면 while문 탈출위해 }; std::queue<_st> Q; void input() { for (int i = 0; i < 4; i++) { scanf("%s", &in_data[i]); for (int j = 0; j < 8; j++) { topni[i][j] = in_data[i][j] - '0'; } } } void clock_wise(int num) { int tmp = topni[num][7]; for (int i = 7; i >= 1; i--) { topni[num][i] = topni[num][i - 1]; } topni[num][0] = tmp; } void non_clock_wise(int num) { int tmp = topni[num][0]; for (int i = 0; i <= 6; i++) { topni[num][i] = topni[num][i + 1]; } topni[num][7] = tmp; //debug(); } void simul(int num, int dir) { Q = {}; // simul함수 여러번 돌릴거라서 초기화 Q.push({ num, dir, 0}); int r = 0; while (!Q.empty()) { _st data = Q.front(); Q.pop(); if (data.flag == 2) return; // 연쇄는 한번 까지만 확인하고 함수 탈출 switch (data.n) // 연쇄 확인 { case 0: r = 0; if (topni[0][2] != topni[1][6]) { r++; Q.push({ 1, -data.d, data.flag + 1 }); } if (r == 1 && topni[1][2] != topni[2][6]) { r++; Q.push({ 2, data.d, data.flag + 1 }); } if (r == 2 && topni[2][2] != topni[3][6]) Q.push({ 3, -data.d, data.flag + 1 }); break; case 1: r = 0; if (topni[1][6] != topni[0][2]) Q.push({ 0, -data.d, data.flag + 1 }); if (topni[1][2] != topni[2][6]) { r++; Q.push({ 2, -data.d, data.flag + 1 }); } if (r == 1 && topni[2][2] != topni[3][6]) Q.push({ 3, data.d, data.flag + 1 }); break; case 2: r = 0; if (topni[2][2] != topni[3][6]) Q.push({ 3, -data.d, data.flag + 1 }); if (topni[2][6] != topni[1][2]) { r++; Q.push({ 1, -data.d, data.flag + 1 }); } if (r == 1 && topni[1][6] != topni[0][2]) Q.push({ 0, data.d, data.flag + 1 }); break; case 3: r = 0; if (topni[3][6] != topni[2][2]) { r++; Q.push({ 2, -data.d, data.flag + 1 }); } if (r == 1 && topni[2][6] != topni[1][2]) { r++; Q.push({ 1, data.d, data.flag + 1 }); } if (r == 2 && topni[1][6] != topni[0][2]) Q.push({ 0, -data.d, data.flag + 1 }); break; } switch (data.d) // 회전 { case 1: clock_wise(data.n); break; case -1: non_clock_wise(data.n); break; } } } void get_rotate() { scanf("%d", &K); for (int i = 0; i < K; i++) { int n = 0, dir = 0; scanf("%d %d", &n, &dir); simul(n - 1, dir); // 0 ~ 3로 인덱싱함 } } int get_score() { int total = 0; for (int i = 0; i < 4; i++) { int dir = topni[i][0]; // i번째 톱니바퀴의 12시방향이 어떤 극인지 total += score[dir][i]; // 0번이면 N극, 1번이면 S극 } return total; } int main() { input(); get_rotate(); int ans = get_score(); printf("%d\n", ans); return 0; }
이 문제 솔직히 재밌게 풀었다 ㅋㅋ 잘 풀리지는 않았지만... 오랜 시간이 걸려서 1트에 성공해서 기부니가 매우 좋았던 문제 ㅎ..
사실 스킬적인 요소보다는 로직을 짤 때 헷갈리지 않는게 중요하다 ... ㅋㅋㅋㅋ 혼동이 될 만한 몇가지 포인트를 제시하자면 다음과 같다.
1. 시계방향으로 회전하는 경우 톱니는 01234567 -> 70123456 순서가 된다. 반 시계방향이면 01234567 -> 12345670 순서가 된다.
2. 연쇄는 한 번만 일어나되, 회전시키기 이전의 상태를 기준으로 한다.
3. 만약 1번 톱니바퀴가 회전하는 경우 4번 톱니바퀴가 회전할 수 있는 경우는 1번 톱니바퀴 회전 -> 2번 톱니바퀴 회전 -> 3번 톱니바퀴 회전이 일어나는 경우이다. 3번 톱니바퀴와 4번톱니바퀴의 맞닿은 극이 다르다고 하더라도, 3번 톱니바퀴가 회전하지 않으면 4번 톱니바퀴는 회전하지 못한다.
// simul( ) 함수
2번 주의사항을 구현하기 위해 각 command마다 flag를 달아주었다. 연쇄는 한번만 일어나야 하므로 flag == 2가 되면 while루프를 빠져나오도록 구현했다. 그리고 회전을 시키기 전에 각 톱니바퀴가 맞닿은 극이 같은지 다른지 판별한 후 큐에 삽입해주었다. 이때 3번 주의사항을 반영하기 위해 r 이라는 플래그를 사용하여 회전 여부를 기록해주었다.
728x90'C 프로그래밍 > BOJ' 카테고리의 다른 글
[백준 16236] 아기 상어 (0) 2022.10.04 [백준 16235] 나무 재테크 (0) 2022.10.03 [백준 11562] 백양로 브레이크 (0) 2022.10.02 [백준 2665] 미로만들기 (0) 2022.10.01 [백준 17141] 연구소 3 (0) 2022.10.01