톱니바퀴를 굴려봐서 마지막 상태를 맞추는 문제다.
역시 삼성 문제답게 시뮬레이션 문제고, 로직은 간단한데 처리할 변수 조건등이 까다롭다.
괜히 n극 s극을 0과 1로 둬서 헷갈리고 회전하는 로직도 헷갈린다.
그래서 함수를 여러개 만들어서 메인 함수에서는 로직을 연결하기만 하는게 중요한거같다.
로직 순서.
1. 재귀 호출을 통해 양옆이 회전 가능한지 체크 (rotateCheck)
2. 체크가 모두 끝났으면 체크 된것들을 회전 (rotate)
각 회전마다 방향이 다르기때문에 rotate안에서 하나씩 처리(rotateOne)
3. 점수 계산(score)
신경쓸게 많아서 그런지 톱니 갯수랑 처음 0부터 시작하는지 1부터 시작하는지를 명확히 하지않아
시간이 걸렸다.
/**
* 백준 14891
* 시뮬레이션
*/
#include <bits/stdc++.h>
#define gearNum 4
#define wheelNum 8
using namespace std;
int gear[gearNum][wheelNum];
int head[gearNum];
bool isRotate[gearNum];
void rotateOne(int wheel,int d){
if(d==1){
// 시계
head[wheel]=((head[wheel]-1+wheelNum)%wheelNum);
}else{
head[wheel]=((head[wheel]+1)%wheelNum);
}
}
void rotateCheck(int wheel,int d){
if(isRotate[wheel]) return;
isRotate[wheel]=true;
// left check
bool lOk=false;
if(wheel-1>=0 && !isRotate[wheel-1]){
// wheel head+6이랑 wheel-1의 2랑 다른 극일때
if(gear[wheel][(head[wheel]+6)%wheelNum]!=gear[wheel-1][(head[wheel-1]+2)%wheelNum]){
lOk=true;
}
}
// right check
bool rOk=false;
if(wheel+1<gearNum && !isRotate[wheel+1]){
// wheel head+2랑 wheel+1의 6이랑 다를때
if(gear[wheel][(head[wheel]+2)%wheelNum]!=gear[wheel+1][(head[wheel+1]+6)%wheelNum]){
rOk=true;
}
}
int od=(d==1)?-1:1;
if(lOk) rotateCheck(wheel-1,od);
if(rOk) rotateCheck(wheel+1,od);
}
void rotate(int start,int d){
int od=(d==1)?-1:1;
for(int i=0;i<gearNum;i++){
if(isRotate[i]){
// 같은 방향
if((start+i)%2==0){
rotateOne(i,d);
}
else{
rotateOne(i,od);
}
}
}
}
int score(void){
int ret=0;
int scores[gearNum]={1,2,4,8};
for(int i=0;i<gearNum;i++){
ret+=(gear[i][head[i]]==1?scores[i]:0);
}
return ret;
}
int main(void){
for(int i=0;i<gearNum;i++){
head[i]=0;
for(int j=0;j<wheelNum;j++){
scanf("%1d",&gear[i][j]);
}
}
int order=0;
cin>>order;
while(order--){
int wheel,d;
cin>>wheel>>d;
wheel--; // 0번 부터 시작
fill(isRotate,isRotate+gearNum,false);
rotateCheck(wheel,d);
rotate(wheel,d);
}
cout<<score()<<endl;
}