코딩테스트/프로그래머스

[프로그래머스] 조이스틱 (C++)

QuickClid 2025. 3. 31. 12:39

아직 풀지 못한 문제이다.


문제 설명

최소 횟수로 조이스틱을 움직여 name을 입력할 때, 그 횟수를 구하시오.

https://school.programmers.co.kr/learn/courses/30/lessons/42860

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

입출력 예

더보기

"JEROEN" 56
"JAN" 23

 

풀이

원하는 알파벳으로 바꾸기 위해서 요구되는 이동 횟수는 언제나 일정하다 --> min(name[i] - 'A', 26 - (name[i] - 'A'));

 

그러므로 이 문제에선 좌우 이동횟수를 최소화하는 것이 핵심이다. --> 그리디 알고리즘을 이용하면 가능하다. 

 

그러나 그리디 알고리즘을 통해 해를 구하는 과정에서, 좌-우 이동의 가중치가 같다면, 어느 방향을 선택할 것인지에 대해서 잘 결정해야 하는데, 그걸 아직 하지 못했다. 예를 들어, BBAAAAABBB에서 기댓값은 10이지만, 이걸 좌-우 이동의 가중치로만 결정하면, 12가 나올 수도 있다.

 

코드

#include <vector>
#include <string>
#include <iostream>

using namespace std;

int solution(string name)
{
    int answer = 0;

    // 적어도 이 횟수만큼은 무조건 조이스틱을 움직여야 함
    for (int i = 0; i < name.length(); i++)
        answer += min(name[i] - 'A', 26 - (name[i] - 'A'));
    cout << "essential : " << answer << endl;

    // greedy
    int right_weight;
    int left_weight;
    int r_move_point;
    int l_move_point;
    int unvisited_right;
    int unvisited_left;
    int limit;
    vector<bool> is_visited;
    for (int i = 0; i < name.length(); i++)
        is_visited.push_back(false);
    int i = 0; // current position
    
    while (true)
    {
        is_visited[i] = true;
        unvisited_right = 0;
        unvisited_left = 0;

        // 오른쪽 진행
        limit = 0;
        for (int j = i; j < name.length();)
        {
            j++;
            limit++;
            if (limit >= name.length()) // 다른, A가 아닌 문자를 찾지 못함.
            {
                right_weight = -1;
                break;
            }
            if (j >= name.length())
            {
                j = 0;
            }
            if (name[j] != 'A' && is_visited[j] == false)
            {
                r_move_point = j;
                right_weight = limit;
                for (int k = i; k < name.length(); k++)
                {
                    if (name[k] != 'A' && !is_visited[k])
                        unvisited_right++;
                }
                break;
            }
        }

        // 왼쪽 진행
        limit = 0;
        for (int j = i; j >= 0;)
        {
            j--;
            limit++;
            if (limit >= name.length()) // 다른, A가 아닌 문자를 찾지 못함.
            {
                left_weight = -1;
                break;
            }
            if (j < 0)
            {
                j = name.length() - 1;
            }
            if (name[j] != 'A' && is_visited[j] == false)
            {
                l_move_point = j;
                left_weight = limit;
                for (int k = i; k >= 0; k--)
                {
                    if (name[k] != 'A' && !is_visited[k])
                        unvisited_left++;
                }
                break;
            }
        }

        // conclude
        cout << "current char : " << name[i] << " | left : " << left_weight << " | right : " << right_weight << endl;
        if (left_weight > right_weight)
        {
            cout << "RIGHT!!!" << endl;
            i = r_move_point;
            answer += right_weight;
        }
        else if (left_weight < right_weight)
        {
            cout << "LEFT!!!" << endl;
            i = l_move_point;
            answer += left_weight;
        }
        else // left_weight == right_weight
        {
            // 둘 다 -1인 경우 무조건 여기로 오게 되어있음
            if (right_weight == -1 && left_weight == -1) // 종료 조건
                break;
            else
            {
                if (unvisited_right > unvisited_left)
                {
                    cout << "NEUTRAL-RIGHT!!!" << endl;
                    // right
                    i = r_move_point;
                    answer += right_weight;
                }
                else
                {
                    cout << "NEUTRAL-LEFT!!!" << endl;
                    // left
                    i = l_move_point;
                    answer += left_weight;
                }
            }
        }
    }

    return answer;
}

int main(void)
{
    //string name = "JAN";
    //string name = "JEOREN";
    //string name = "AAZ";
    //string name = "BBAAAB";
    //string name = "ABAAAB";
    string name = "BBAAAAABBB"; // 황금 반례
    //string name = "BBBAAAAABBB";
    cout << solution(name);
}