2011-11-28 4 views
1

따라 행렬 번 클릭으로

10001 
10100 
00000 
00000 
00111 
00100 
00100 

주어진다 프로그래밍 퍼즐을위한 알고리즘을 제안 화소 충전 도구 흰색 하나로 각각의 블랙 픽셀을 턴 이전 픽셀. 픽셀은 북쪽, 남쪽, 동쪽, 서쪽 및 4 개의 대각선과 같이 최대 8 가지 방법으로 다른 픽셀과 연결됩니다.

퍼즐 링크이 내가 그것을 해결하는 방법입니다 http://www.gild.com/challenges/details/295#

입니다. 누구나이 문제가 어느 알고리즘 범주에 속하는 지 알 수 있습니다.

#include <stdio.h> 
#include <vector> 
#include <fstream> 
#include <sstream> 
#include <iostream> 
#include <deque> 

typedef std::vector<std::vector<bool> > table_t; 


class Solver { 
public: 
    Solver(int H, int W): _height(H), 
     _width(W), 
     T(H, std::vector<bool>(W)), 
     num_of_clicks(0){ 
    } 
    ~Solver() { 
    } 
    void ReadFile(std::ifstream &ifs){ 
     int row = 0, col = 0; 
     std::string file_line; 
     while(ifs.good()) { 
      std::getline(ifs,file_line); 
      for (std::string::const_iterator it = file_line.begin(); it != file_line.end(); ++it) { 
       if (*it - '0' == 1) { 
        T[row][col++] = true; 
       } else { 
        T[row][col++] = false; 
       }    
      } 
      col = 0; 
      row++;   
     } 
     ifs.close(); 
    } 
    void solve() { 
     for (int row = 0; row < _height; ++row) { 
      for (int col = 0; col < _width; ++col) { 
       if (T[row][col] == true) 
        continue; 
       neighbours.clear(); 
       num_of_clicks++; 
       neighbours.push_back(std::make_pair(row,col)); 
       while (!neighbours.empty()) { 
        std::pair<int,int> elem = neighbours.front(); 
        neighbours.pop_front(); 

        int R = elem.first; 
        int C = elem.second;      

        west  (R, C); 
        east  (R, C); 
        north  (R, C); 
        south  (R, C); 
        north_west (R, C); 
        south_west (R, C); 
        south_east (R, C); 
        north_east (R, C); 
       } 
      } // colum loop ends here 
     } // row loop ends here 
     std::cout << num_of_clicks << std::endl; 
    } 
private: 
    int _height; 
    int _width; 
    table_t T; 
    std::deque<std::pair<int,int> > neighbours; 
    int num_of_clicks; 

    void west(int row, int col) { 
     if (col - 1 >= 0 && T[row][col - 1 ] == false) { 
      T[row][col - 1 ] = true; 
      neighbours.push_back(std::make_pair(row, col - 1)); 
     } 
    } 

    void east(int row, int col) { 
     if (col + 1 < _width && T[row][col + 1 ] == false) { 
      T[row][col + 1 ] = true; 
      neighbours.push_back(std::make_pair(row, col + 1)); 
     } 
    } 

    void north(int row, int col) { 
     if (row - 1 >= 0 && T[row - 1][col] == false) { 
      T[row - 1][col] = true; 
      neighbours.push_back(std::make_pair(row - 1, col)); 
     } 
    } 

    void south(int row, int col) { 
     if (row + 1 < _height && T[row + 1][col] == false) { 
      T[row + 1][col]= true; 
      neighbours.push_back(std::make_pair(row + 1, col)); 
     } 
    } 

    void north_west(int row, int col) { 
     if (row - 1 >= 0 && col - 1 >= 0 && 
      T[row - 1][col - 1] == false) { 
       T[row - 1][col - 1] = true; 
       neighbours.push_back(std::make_pair(row - 1, col - 1)); 
     } 
    } 

    void south_west(int row, int col) { 
     if (row + 1 < _height && col - 1 >= 0 && 
      T[row + 1][ col - 1] == false) { 
       T[row + 1][ col - 1] = true; 
       neighbours.push_back(std::make_pair(row + 1, col - 1)); 
     } 
    } 

    void south_east(int row, int col) { 
     if (row + 1 < _height && col + 1 < _width && 
      T[row + 1][col + 1] == false){ 
       T[row + 1][col + 1] = true; 
       neighbours.push_back(std::make_pair(row + 1, col + 1)); 
     } 
    } 

    void north_east(int row, int col) { 
     if (row - 1 >= 0 && col + 1 < _width && 
      T[row - 1][col + 1] == false) { 
       T[row - 1][col + 1] = true; 
       neighbours.push_back(std::make_pair(row - 1, col + 1)); 

     } 
    } 
}; 

int main (int argc, char **argv) { 
    int H = 0; 
    int W = 0; 
    std::ifstream input(argv[1]); 
    if (input.peek() == EOF) { 
     return 1; 
    } 
    // Read the first line. 
    std::string file_line; 
    std::getline(input,file_line); 
    std::istringstream iss; 
    iss.clear(); 
    iss.str(file_line); 
    // Get the height and width of the image. 
    iss >> H >> W; 
    Solver s(H,W); 
    s.ReadFile(input); 
    s.solve(); 

    return 0; 
} 
+4

http://en.wikipedia.org/wiki/Flood_fill 아마? –

+0

@BartKiers, 그는 홍수 채우기를하고 있습니다. 코드를 보면 ... – st0le

답변

3

이 칠해 동작 (마커 이미지가 단일 화이트 개시 화소와 원 화상의 역수 인 마스크 화상 블랙 인)와 팽창 의해 형태 재구성 전형적인 애플리케이션이다. 구현과 매우 흡사 한 L. Vincents paper on an efficient implementation을 비교하고 O. Eidheim의 우수 introductory talk을 비교하십시오.

0

호출 된 연결 구성 요소 레이블. 그것의 일반화 된 버전에 주목하십시오. 여기에 Wikipedia entry