ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 14891] 톱니바퀴
    C 프로그래밍/BOJ 2022. 10. 3. 14:58
    728x90

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

     

    14891번: 톱니바퀴

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

    www.acmicpc.net

    #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

    댓글

Designed by Tistory.