인프런 커뮤니티 질문&답변
안녕하세요. 4-B 질문 있습니다.
작성
·
340
0
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! 
- 먼저 유사한 질문이 있었는지 검색해보세요. 
- 서로 예의를 지키며 존중하는 문화를 만들어가요. 
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.
안녕하세요 큰돌님 강의 잘듣고 있습니다.
해당문제 관련해서 질문이 있는데요.
일단 비트마스킹을 이용한 풀이법은 숙지했습니다.
근데 비트마스킹을 안쓰고 풀었을때 처음에 틀렸었는데 제가 아래 올린코드에서 Reverse함수의 기저사례 단락에서 "--->이부분!" 이라고 주석표시한 부분 관련해서 궁금한게 있습니다.
문제에서 동전의 뒤집기 갯수가 2보다 작을수는 없다고 해서, 전 처음에 이게 문제가 답에대한 제한조건을 걸었다고 생각해서 저렇게 2보다 큰 경우에만 min값을 갱신하도록 코드를 짰었는데요.
저 부분을 없애야 정답이더라구요.
큰돌님 풀이에서도 2에 대한 제한조건을 거는 부분은 없는것 같은데, 문제에서 해당 예제에관한 설명이 답의 범위에 대해서 제한을 걸어놓은게 아니라 그냥 " 뒷면갯수가 2보다 작은게 불가능하다" 라고 설명해주는 부분인데 제가 잘못이해한건가요??
#include <iostream>
#include <vector>
#include <string>
#include <thread>
#include <mutex>
#include <limits.h>
using namespace std;
int n;
int coin[21][21];
int minVal=INT_MAX;
void Change(int i, int j) //요소 하나 바꾸기
{
	if (coin[i][j] == 1)
		coin[i][j]= 0;
	else
		coin[i][j]= 1;
}
void ChangeAll(int length, char hw ,int fix) // 한줄 바꾸기('h' : 행 고정 / 'w' : 열 고정)
{
	if (hw == 'h') 
		for (int i = 0; i < length; ++i)
			Change(fix, i);
	if (hw == 'w') 
		for (int i = 0; i < length; ++i)
			Change(i, fix);
}
void Reverse(int length, char fix, int fixPos) // 행 다 모든 경우의수로 다 뒤집고 열 하나씩 뒤집어보기
{
	if (fixPos == length) {
		int ret = 0;
		for (int i = 0; i < length; ++i) {
			int sum = 0;
			for (int j = 0; j < length; ++j){
				sum += coin[j][i];
			}
			if ((length - sum) > sum) 
				ret += sum;
			else
				ret += (length - sum);
		}
		if(ret>=2)  //------------------> 이부분!
			minVal = min(minVal, ret);
		return;
	}
	if (fix == 'h'){
		for (int i = 0; i < 2; ++i){
			ChangeAll(length, fix, fixPos);
			Reverse(length, fix, fixPos + 1);
		}
	}
	if (fix == 'w') {
		for (int i = 0; i < 2; ++i){
			ChangeAll(length, fix, fixPos);
			Reverse(length, fix, fixPos + 1);
		}
	}
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cin >> n;
	for (int i = 0; i < n; ++i) {
		string s;
		cin >> s;
		for (int j = 0; j < n; ++j) {
			if (s[j] == 'H')
				coin[i][j] = 'H' - 'H' + 1;
			else
				coin[i][j] = 'T' - 'T';
		}
	}
	Reverse(n, 'h', 0);
	cout << minVal << '\n';
}
답변 1
0
안녕하세요 KEI님 ㅎㅎ
혹시
문제에서 동전의 뒤집기 갯수가 2보다 작을수는 없다고 해서, 전 처음에 이게 문제가 답에대한 제한조건을 걸었다고 생각해서 저렇게 2보다 큰 경우에만 min값을 갱신하도록 코드를 짰었는데요.
이부분이요. 왜 2보다 작을수는 없다고 생각하시나요?
제 코드를 기반으로 설명하면
		int sum = 0; 
		for(int i = 1; i <= (1 << (n - 1)); i *= 2){
			int cnt = 0; 
			for(int j = 1; j <= n; j++) if(a[j] & i)cnt++;
			sum += min(cnt, n - cnt); 
		}이런건데 이상적으로 다 뒤집어져있다면 뒤가 0인 경우의 수도 생기지 않을까요??
감사합니다.






"<그림 3>의 상태에서 뒷면이 위를 향하여 놓인 동전의 개수는 두 개이다. <그림 1>의 상태에서 이와 같이 한 행 또는 한 열에 놓인 N개의 동전을 모두 뒤집는 작업을 계속 수행할 때 뒷면이 위를 향하도록 놓인 동전의 개수를 2개보다 작게 만들 수는 없다."
문제 지문중 일부분인데, 지금 다시 보니까 당연히 해당 예제에 국한해서 하는말인데 정신없이 읽다보니까 착각했네요