본문 바로가기

그리디 알고리즘

동전 뒤집기

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

 

1285번: 동전 뒤집기

첫째 줄에 20이하의 자연수 N이 주어진다. 둘째 줄부터 N줄에 걸쳐 N개씩 동전들의 초기 상태가 주어진다. 각 줄에는 한 행에 놓인 N개의 동전의 상태가 왼쪽부터 차례대로 주어지는데, 앞면이 위

www.acmicpc.net

임의의 한 행, 한 열에 놓은 N개의 동전을 뒤집는다.

동전을 적절히 뒤집어 T의 최소 개수 구하기

 

각 동전은 행 또는 열을 바꿀 때, 그 결과가 바뀔 수 있다. 즉, 모든 동전은 2번의 변환이 가능하다.

따라서 접근 방식은 다음과 같다. 3x3 크기의 행렬로 동전이 있다고 가정하자.

그러면, 행을 바꾸는 경우는 아래와 같이 총 7가지가 있다.

① 모든 행을 바꾸지 않는 1가지
② 모든 행을 다 바꾸는 1가지
③ 2개의 행을 골라 바꾸는 3가지
④ 1개의 행을 골라 바꾸는 3가지

 

하나의 열의 동전의 총 개수는 N개로 동일하기 때문에 뒤집은 경우와 뒤집지 않은 경우 중

더 적은 경우로 계산을 하면 됨.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <string>
#include <vector>
 
using namespace std;
 
char flip(char x)
{
    if (x == 'H'return 'T';
    else return 'H';
}
 
int main()
{
    int n;
    cin >> n;
    vector<string> a(n);
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    int ans = n * n;
 
    //state는 행을 바꿀지 말지를 의미
    //모든 경우의 수 표현을 위해 비트마스크
    for (int state = 0; state < (1 << n); state++)
    {
        int sum = 0;
 
        // j는 열
        for (int j = 0; j < n; j++)
        {
            int cnt = 0;
            // i는 행
            for (int i = 0; i < n; i++)
            {
                char cur = a[i][j];
                // 비트마스크를 통해 뒤집는지 안 뒤집는지 결정
                if (state & (1 << i))
                    cur = flip(cur);
                
                if (cur == 'T')
                    cnt += 1;
            }
            // 열은 뒤집을 필요가 없다.
            // 개수가 적은 걸 고르면 그걸 뒤집은 걸로 생각하면 끝
            sum += min(cnt, n - cnt);
        }
 
        if (ans > sum) ans = sum;
    }
    cout << ans << '\n';
    return 0;
}
cs

'그리디 알고리즘' 카테고리의 다른 글

전구와 스위치  (0) 2023.06.21
행렬  (0) 2023.06.20
회의실 배정  (0) 2023.05.11
동전 0  (0) 2023.05.11
Opening Ceremony  (0) 2023.04.29