[BOJ][C#] 14891 톱니바퀴

LimJaeJun·2023년 10월 21일
0

PS/BOJ

목록 보기
34/108

📕 문제

📌 링크


📗 접근 방식

  • 기어 표현 및 초기 설정:

    • 입력을 받아 각 기어를 나타내는 Gear 클래스를 생성합니다.
    • Gear 클래스는 8개의 부분(parts)과 가운데 부분(center)을 가지며, 회전 방향을 표시하는 score를 가집니다.
      • 배열을 움직이는 것이 아니라 12시 방향의 인덱스를 center로 저장하여 회전시 인덱스 번호만 변경하여 회전하는 로직 만듦
      • score는 쉬프트 연산을 통해 데이터 저장
  • 회전 시뮬레이션:

    • 큐(회전시켜야하는 기어, 회전 방향) 사용
    • 회전 명령을 받으면, 해당 기어와 연관된 인접한 기어를 확인하여 회전
    • 두 기어를 비교하여 다른 경우 회전 방향을 변경하고 큐에 추가
    • 큐를 사용하여 인접한 기어를 모두 확인하고 회전 방향을 업데이트
  • 점수 계산:

    • 모든 회전이 끝나면, 각 기어의 가운데 부분(center)에 있는 값이 1인 경우에 해당 기어의 score를 누적하여 결과를 계산
  • 결과 출력

    • 최종 결과를 출력합니다.

📘 코드

using System;
using System.Collections.Generic;

class Program
{
    const int MAX_GEAR_NUM = 4;
    const int MAX_GEAR_PARTS_NUM = 8;

    class Gear
    {
        //public string Name;
        private int[] parts = new int[MAX_GEAR_PARTS_NUM];
        private int center = 0;
        private int score = 0;

        public Gear(string s, int score)
        {
            for(int i = 0 ; i < s.Length ; i++)
            {
                this.parts[i] = int.Parse(s[i].ToString());
            }

            this.score = score;
        }

        public int GetScore()
        {
            return parts[center] == 1 ? score : 0;
        }

        public int GetValue(int index)
        {
            return parts[index];
        }

        public int GetRightIndex()
        {
            int ret = center;

            ret += 2;

            return CheckIndex(ret);
        }

        public int GetLeftIndex()
        {
            int ret = center;

            ret -= 2;

            return CheckIndex(ret);
        }

        public void Rotation(int num)
        {
            if(num == 1) Right();
            else Left();
        }

        private void Right()
        {
            center--;

            center = CheckIndex(center);
        }

        private void Left()
        {
            center++;

            center = CheckIndex(center);
        }

        private int CheckIndex(int index)
        {
            int min = 0;
            int max = parts.Length;

            if(index < min)
                index += max;
            else if(index >= max)
                index -= max;

            return index;
        }
    }

    static void Main()
    {
        List<Gear> gears = new List<Gear>();

        int score = 1;
        for(int i=0 ;i<MAX_GEAR_NUM ;i++)
        {
            Gear newGear = new Gear(Console.ReadLine(), score);
            //newGear.Name = $"{i}번째 기어";
            gears.Add(newGear);
            score <<= 1;
        }

        int k = int.Parse(Console.ReadLine());

        int[] inputs;
        Queue<(Gear, int)> q = new Queue<(Gear, int)>();
        for(int i=0 ;i<k ;i++)
        {
            inputs = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
            int gearIndex = inputs[0] - 1;
            int rotation = inputs[1];

            q.Clear();

            var rot = rotation;
            for(int index =gearIndex ;index>0 ;index--)
            {
                Gear centerGear = gears[index];
                Gear leftGear = gears[index - 1];

                int centerToLeftIndex = centerGear.GetLeftIndex();
                int leftToRightIndex = leftGear.GetRightIndex();

                int center = centerGear.GetValue(centerToLeftIndex);
                int left = leftGear.GetValue(leftToRightIndex);
                //Console.WriteLine($"{centerGear.Name}:{centerToLeftIndex} {leftGear.Name}:{leftToRightIndex} 비교");
                if(center != left)
                {
                    rot = -rot;
                    q.Enqueue((leftGear, rot));
                }
                else break;
            }

            rot = rotation;
            for(int index=gearIndex ;index<MAX_GEAR_NUM-1 ;index++)
            {
                Gear centerGear = gears[index];
                Gear rightGear = gears[index + 1];

                int centerToRightIndex = centerGear.GetRightIndex();
                int rightToLeftIndex = rightGear.GetLeftIndex();

                int center = centerGear.GetValue(centerToRightIndex);
                int right = rightGear.GetValue(rightToLeftIndex);
                //Console.WriteLine($"{centerGear.Name}:{centerToRightIndex} {rightGear.Name}:{rightToLeftIndex} 비교");
                if(center != right)
                {
                    rot = -rot;
                    q.Enqueue((rightGear, rot));
                }
                else break;
            }

            while(q.Count >0)
            {
                var cur = q.Dequeue();
                cur.Item1.Rotation(cur.Item2);
                string s1 = cur.Item2 == 1 ? "오른쪽" : "왼쪽";
                //Console.WriteLine($"{cur.Item1.Name} {s1} 회전");
            }

            gears[gearIndex].Rotation(rotation);
            string s = rotation == 1 ? "오른쪽" : "왼쪽";
            //Console.WriteLine($"{gears[gearIndex].Name} {s} 회전");
        }

        int answer = 0;
        foreach(var gear in gears)
        {
            answer += gear.GetScore();
        }

        Console.WriteLine(answer);
    }
}

📙 오답노트

📒 알고리즘 분류

  • 구현
  • 시뮬레이션

⏰ 소요시간

3시간

profile
Dreams Come True

0개의 댓글

관련 채용 정보