본문 바로가기

Algorithm/PS

[1일 1알고] 2차원 동전 뒤집기

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

 

프로그래머스

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

programmers.co.kr

구현 문제입니다.

 

어떻게 뒤집어야하는지는 하나의 열 혹은 행에 대한 상태를 결정하면 나머지는 뒤따라옵니다.

 

하나의 열을 결정하면 target에 맞추기 위해 행의 flip상태가 모두 결정나고 반대로도 마찬가지입니다.

 

따라서 첫번째 열을 뒤집은 경우, 그대로 둔 경우로 나눠 이후 구현해나가면 됩니다.

 

문제는 XOR를 적극적으로 사용할 것을 권장하는 것 처럼 보입니다.

flip을 하기 위한 가장 간단한 방법은 0과 1로 이루어진 기존 값에 XOR1을 하는 것이기 때문입니다.


#include <string>
#include <vector>

using namespace std;


int solution(vector<vector<int>> beginning, vector<vector<int>> target) {
    int answer = -1;

    int N = beginning.size();
    int M = beginning[0].size();
    vector<int> columns(M, 0); // 0 = 그대로, 1 = flip

    int colcnt = 0;
    // 첫 행은 그대로라고 가정
    for (int j = 0; j < M; ++j)
    {
        if (beginning[0][j] != target[0][j])
        {
            columns[j] = 1;
            ++colcnt;
        }
    }

    int temp = 0;
    for (int i = 1; i < N; ++i)
    {
        bool flag = true;
        for (int j = 0; j < M; ++j)
        {
            int cur = beginning[i][j] ^ columns[j];

            if (cur != target[i][j])
            {
                flag = false;
                break;
            }
        }
        if (flag)
            continue;
        flag = true;
        for (int j = 0; j < M; ++j)
        {
            int cur = beginning[i][j] ^ 1 ^ columns[j];

            if (cur != target[i][j])
            {
                flag = false;
                break;
            }
        }

        if (flag)
        {
            ++temp;
        }
        else
        {
            temp = -1;
            break;
        }
    }

    if (temp != -1)
    {
        answer = temp + colcnt;
    }

    for (int i = 0; i < M; ++i)
    {
        columns[i] ^= 1;
    }
    colcnt = M - colcnt;

    temp = 0;
    // 첫 행이 뒤집힌 경우
    for (int i = 1; i < N; ++i)
    {
        bool flag = true;
        for (int j = 0; j < M; ++j)
        {
            int cur = beginning[i][j] ^ columns[j];

            if (cur != target[i][j])
            {
                flag = false;
                break;
            }
        }
        if (flag)
            continue;
        flag = true;
        for (int j = 0; j < M; ++j)
        {
            int cur = beginning[i][j] ^ 1 ^ columns[j];

            if (cur != target[i][j])
            {
                flag = false;
                break;
            }
        }

        if (flag)
        {
            ++temp;
        }
        else
        {
            temp = -1;
            break;
        }
    }
    if (temp != -1)
    {
        int cur = temp + colcnt + 1;

        if (answer == -1)
            answer = cur;
        else
            answer = min(answer, cur);
    }

    return answer;
}

결론적인 코드입니다.

반복되는 부분이 있지만 모듈화를 한다면 더 간단하게 풀 수 있겠네요


#include <string>
#include <vector>
#include <algorithm>

using namespace std;

int check(const vector<vector<int>>& beginning,
          const vector<vector<int>>& target,
          bool flipFirstRow)
{
    int N = beginning.size();
    int M = beginning[0].size();

    vector<int> colFlip(M, 0);
    int count = 0;

    // 첫 행을 뒤집는 경우라면 count 1 증가
    if (flipFirstRow)
        ++count;

    // 첫 행을 기준으로 각 열을 뒤집을지 결정
    for (int j = 0; j < M; ++j)
    {
        int cur = beginning[0][j];

        if (flipFirstRow)
            cur ^= 1;

        if (cur != target[0][j])
        {
            colFlip[j] = 1;
            ++count;
        }
    }

    // 나머지 행 검사
    for (int i = 1; i < N; ++i)
    {
        bool same = true;
        bool reversed = true;

        for (int j = 0; j < M; ++j)
        {
            int cur = beginning[i][j] ^ colFlip[j];

            // 행을 안 뒤집었을 때 맞는가?
            if (cur != target[i][j])
                same = false;

            // 행을 뒤집었을 때 맞는가?
            if ((cur ^ 1) != target[i][j])
                reversed = false;
        }

        if (same)
        {
            continue;
        }
        else if (reversed)
        {
            ++count;
        }
        else
        {
            return -1;
        }
    }

    return count;
}

int solution(vector<vector<int>> beginning, vector<vector<int>> target)
{
    int case1 = check(beginning, target, false); // 첫 행 안 뒤집음
    int case2 = check(beginning, target, true);  // 첫 행 뒤집음

    if (case1 == -1 && case2 == -1)
        return -1;

    if (case1 == -1)
        return case2;

    if (case2 == -1)
        return case1;

    return min(case1, case2);
}

이는 AI를 통해 만든 코드입니다. 전체적인 가닥은 비슷하지만 check라는 함수를 만들어 분리해주었네요

'Algorithm > PS' 카테고리의 다른 글

[1일 1알고] 모두 0으로 만들기  (0) 2026.05.27
[1일 1알고] 등대  (0) 2026.05.26
[1일 1알고] 디스크 컨트롤러  (0) 2026.05.21
[1일 1알고] 징검다리 건너기  (0) 2026.05.20
[1일 1알고] 보행자 천국  (0) 2026.05.19