기본 콘텐츠로 건너뛰기

K사 : 같은 색깔의 블록 갯수 구하기 (Flood Fill)(Recursive) [C,C++]

K사의 17년도 1번 문제이다.

문제를 한 마디로 말하면

'가장 많은 그룹을 가진 색의 그룹 개수와 최대 색칠 개수를 세라' 인데

이해하기 어려우시죠?

그림으로 보여드리겠습니다.


여기서 가장 많은 그룹을 가진 색은 빨간색입니다.
그룹의 개수는 4개입니다.
최대 색칠 개수는 오른쪽 위에 있는 43개입니다.

이해가 가시나요?

재귀 알고리즘 중 하나인 Flood Fill 알고리즘을 이용해 푸는 문제입니다.

계속 방문하여 개수를 체크 후에 더 체크할 게 없다면 return하는 방식입니다.

색깔을 찾는 코드만 짤 수 있으면 이 문제도 풀 수 있기 때문에

저는 하얀 배경에서 검은 색깔을 찾는 코드를 만들었습니다.

여러 색깔을 담는 배열 하나만 만들어주면 바로 바꿀 수 있는 문제입니다.

void MoveDirection(vector<vector<int>> &picture, int row, int column, int count)
{
 picture[row][column] = -1;
 
 count++;
 if (count > MaxCount)
  MaxCount = count;
 
 if (column < picture[0].size() - 1)
 {
  if (picture[row][column + 1] > 0) // RIGHT
   MoveDirection(picture, row, column + 1, count);
 }
 if (column > 0)
 {
  if (picture[row ][column - 1] > 0) // LEFT
   MoveDirection(picture, row, column - 1, count);
 }
 if (row > 0)
 {
  if (picture[row - 1][column] > 0) // UP
   MoveDirection(picture, row - 1, column, count);
 }
 if (row < picture.size() - 1)
 {
  if (picture[row + 1][column] > 0) // DOWN
   MoveDirection(picture, row + 1, column, count);
 }
}

vector<int> solution(vector<vector<int>> &picture)
{
 for (int iIndex = 0; iIndex < picture.size(); iIndex++)
 {
  for (int jIndex = 0; jIndex < picture[0].size(); jIndex++)
  {
   if (picture[iIndex][jIndex] > 0)
   {
    MoveDirection(picture, iIndex, jIndex, 0);
    PartCount++;
   }
  }
 }

 vector<int> answer = { PartCount, MaxCount };
 return answer;
}
<검정색의 그룹 개수와 최대 색칠 개수를 찾는 코드>

댓글

이 블로그의 인기 게시물

1094 : 막대기 [C++]

# include < iostream > # include < vector > using namespace std ; int main ( ) { vector < int > Stick ; Stick . push_back ( 64 ) ; int Target ; cin > > Target ; int Last = 0 ; while ( true ) { if ( Target = = 64 ) break ; int Sum = 0 ; for ( int i = 0 ; i < Stick . size ( ) ; i + + ) Sum + = Stick [ i ] ; if ( Target = = Sum ) break ; else if ( Target < Sum ) { Stick [ Last ] / = 2 ; Sum = 0 ; for ( int i = 0 ; i < Stick . size ( ) ; i + + ) Sum + = Stick [ i ] ; if ( Target < = Sum ) continue ; else Stick . push_back ( Stick [ Last + + ] ) ; } } cout < < Stick . size ( ) ; ...

2407 : 조합 (Dynamic Programming) [C++]

어려웠다. 문제를 풀면서 솔직히 이게 되려나?? 메모리 제한걸리려는게 아닌가 싶었는데 만들면서 최대한 메모리를 작게 만들었더니 맞았습니다! 주어진 입력 값은 최대 100인데, 입력값을 입력하면 오버플로우가 나므로 자릿수 배열을 만들어주어야 한다! 처음으로 한 생각은 재귀! (n == m || m == 0) 참이면 1 거짓이면 [n-1], [n]번째에 계속 접근하기 결과는 20이 넘어가면 엄청난 시간이 걸림. 두 번째 한 생각은 3차원 배열이었다. 2차원 배열에 또 배열을 만들어 자릿 수를 다 저장하려 했으나~ for문이 3개나 들어가서 시간이 엄청 오래걸렸음. 결국 2차원 배열이지만 3차원의 효과를 내게끔 선언하였다. 2차원배열이 원래이런 식이라면 1 11 121 1331 14641 내가 만든 배열은 111121133114641 즉 한 차원을 줄일 수 있었고, 각 원소에 대한 파스칼의 삼각형을 이용한 덧셈 공식은  그 줄의 자릿수 사이즈를 이용하여 전에 있는 줄에 접근하였다. DP 사용!! Answer[i] = Answer[i-Answer[i].size()] + Answer[i-Answer[i].size()+1] 그리고 저장한 자릿수들을 거꾸로 출력해주면 그것이 정답! Combination() : 각 줄의 번호만큼 자릿수를 가지는 벡터 생성, 계속 쓰는 Sum 벡터 생성 Increase() : 각 자릿수가 10이 넘어가면 올림을 해준다. GetSum() : 각 자릿수를 더해준다. GetAnswer() : DP, 올림, 출력  Combination :: Combination ( ) { this - > Sum . push_back ( 0 ) ; for ( int i = 1 ; i < = 101 ; i + + ) Sum . push_back ( S...

11401 : 이항계수 3 (Dynamic Programming, Divide and Conquer) [C++]

1번, 2번 문제들과 확연히 차이나는 입력의 범위. 400만 ! DP를 사용해서 풀 수 없는 문제이다 . 하지만 DP가 쓰이긴 한다! 수학은 너무 어렵다. 곱셈의 역원을 공부해보다가 모르겠어서 도움을 구했다. 왜 곱셈의 역원을 구해야하는가? N! / (K! * (N-K)!) 에서 K! * (N-K)! 의 역원을 구해야 하기 때문! 곱셈의 역원을 구하는 정리인 페르마의 소정리를 이용하면 p가 1000000007 이지만 분할 정복을 이용한 제곱 수 계산 덕분에 logP 시간 소요. 분할 정복을 이용한 제곱 수 계산은 계속 써먹을 것 같아서 따로 올려놓았다. DP가 쓰이는 부분은 구해준 400만의 역원을 바탕으로 모든 역원을 구하는 부분이다. 그러므로 총 시간 소요는 O(N+LogP) long long BinomialCoefficient :: GetNum ( int N , int K ) { this - > Factorial [ 1 ] = 1 ; for ( int i = 2 ; i < = 4000000 ; i + + ) this - > Factorial [ i ] = ( this - > Factorial [ i - 1 ] * i ) % P ; this - > Invert [ 4000000 ] = this - > Pow_DC ( this - > Factorial [ 4000000 ] , P - 2 ) ; for ( int i = 4000000 - 1 ; i > 0 ; i - - ) this - > Invert [ i ] = ( this - > Invert [ i + 1 ] * ( i + 1 ) ) % P ; if ( N = = K | | K = ...