반응형
1. 각 행을 뒤집을지 여부를 고정한다.
2. 각 열을 뒤집을지 말지 여부를 tail 개수가 최소가 되도록 그리디 하게 정한다.
1. 각 행을 뒤집을지 여부를 고정한다.
행이 최대 20개, 열이 최대 20개이므로 각 행과 열에 대해 뒤집을지 말지 여부를 결정하는 경우의 수는 2^40가지이다. 따라서 브루트 포스로는 시간 내에 해결할 수 없다. 먼저 행에 대해서만 뒤집을지 여부를 결정해주자. 경우의 수는 2^20가지로 줄어든다.
2. 각 열을 뒤집을지 말지 여부를 tail 개수가 최소가 되도록 그리디하게 정한다.
행을 뒤집을지 말지 여부를 결정하고 나면, 이제 각 열의 뒤집을지 말지 여부는 그리디 하게 정할 수 있게 된다. 각 열끼리는 서로 영향을 미치지 않으므로, 각 열에 대해 뒤집는 경우와 뒤집지 않는 경우 중 더 tail이 적어지는 쪽을 택하면 된다. 이 과정의 시간 복잡도는 O(N^2)이 되므로, 최종 시간 복잡도는 O(N^2 * 2^N).
반응형
#include <iostream>
using namespace std;
int N;
string board[20];
// makeMinTail(row): 각 행을 뒤집을지 여부가 row로 주어졌을 때, 뒷면의 최소 개수
int makeMinTail(int row) {
int ret = 0;
// 각 열을 뒤집을지 말지 여부를 tail 개수가 최소가 되도록 정한다.
for (int j=0; j<N; j++) {
int headCnt = 0;
for (int i=0; i<N; i++) {
bool head = board[i][j] == 'H';
if ((row & (1 << i)) != 0) head = !head;
if (head) headCnt++;
}
ret += min(headCnt, N - headCnt);
}
return ret;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> N;
for (int i=0; i<N; i++) cin >> board[i];
int ans = 987654321;
for (int i=0; i<(1 << N); i++) {
ans = min(ans, makeMinTail(i));
}
cout << ans;
return 0;
}
반응형
'Problem Solving > BOJ' 카테고리의 다른 글
백준 1450번 냅색문제 - C++ 풀이 (0) | 2022.07.01 |
---|---|
백준 12837번 가계부 (Hard) - C++ 풀이 (0) | 2022.06.29 |
백준 15684번 사다리 조작 - C++ 풀이 (0) | 2022.06.24 |
백준 10974번 모든 순열 - C++ 풀이 (0) | 2022.06.23 |
백준 10799번 쇠막대기 - C++ 풀이 (0) | 2022.06.17 |
댓글