인프런 커뮤니티 질문&답변

kei jay님의 프로필 이미지
kei jay

작성한 질문수

10주완성 C++ 코딩테스트 | 알고리즘 코딩테스트

4-B

안녕하세요. 4-B 질문 있습니다.

작성

·

306

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인 경우의 수도 생기지 않을까요??

 

감사합니다.

kei jay님의 프로필 이미지
kei jay
질문자

"<그림 3>의 상태에서 뒷면이 위를 향하여 놓인 동전의 개수는 두 개이다. <그림 1>의 상태에서 이와 같이 한 행 또는 한 열에 놓인 N개의 동전을 모두 뒤집는 작업을 계속 수행할 때 뒷면이 위를 향하도록 놓인 동전의 개수를 2개보다 작게 만들 수는 없다."

문제 지문중 일부분인데, 지금 다시 보니까 당연히 해당 예제에 국한해서 하는말인데 정신없이 읽다보니까 착각했네요

kei jay님의 프로필 이미지
kei jay

작성한 질문수

질문하기