알고리즘 트레이닝북의 그래픽 에디터 문제..

  • jspac
    jspac

    일단 샘플 케이스로 테스트 해봤을 때는 맞는 결과가 나오는데,
    서브미션에서는 WA가 뜨네요..

    Fill 명령 구현이 뭔가 문제가 있는 것 같은데,
    뭐가 잘못된 건지 모르겠어요 ㅠ.ㅠ
    extreme test case로 어떤 것들이 있는지도 모르겠구요;;;
    먼저 원래 색을 저장하고, 그 색을 가진 동서남북의 점들을 찾아서 입력받은 색으로 바꿔놓은 다음에
    그 다음 턴에서 찾은 점들 각각을 중심으로 또 동서남북 중 매치를 찾는 방식의 반복문으로 짰는데요...
    이런 방식으로 하면 어떤 경우에 잘못된 결과가 나오는 걸까요??

    일단 소스 코드는 다음과 같습니다 (HTML 태그는 못쓰는군요;;;):

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char **init(int, int);
    void clear(char **, int, int);
    void empty(char **, int, int);
    void print(char *, char **, int, int);
    void fill_region(char **, int, int, int, int, char);
    
    #define EXTRACT_COLOR len = strlen(command) - 1; while ((c = command[len]) < 'A') len--; command[len] = '\0';
    #define COLOR_PX canvas[y - 1][x - 1] = c;
    #define DRAW_VSEG x--; if (y1 <= y2) for (y = y1 - 1; y < y2; y++) canvas[y][x] = c; else for (y = y2 - 1; y < y1; y++) canvas[y][x] = c;
    #define DRAW_HSEG y--; if (x1 <= x2) for (x = x1 - 1; x < x2; x++) canvas[y][x] = c; else for (x = x2 - 1; x < x1; x++) canvas[y][x] = c;
    #define FILL_RECT for (y = y1 - 1; y < y2; y++) for (x = x1 - 1; x < x2; x++) canvas[y][x] = c;
    
    int main(void)
    {
      char c, command[50], name[50], **canvas;
      int len, cols = 0, rows, x, y, x1, y1, x2, y2;
    
      while (1)
      {
        fgets(command, 50, stdin);
        switch (command[0])
        {
          case 'I':
            empty(canvas, cols, rows);
            sscanf(command + 1, "%d %d", &cols, &rows);
            canvas = init(cols, rows);
            break;
          case 'C':
            clear(canvas, cols, rows);
            break;
          case 'L':
            EXTRACT_COLOR;
            sscanf(command + 1, "%d %d", &x, &y);
            COLOR_PX;
            break;
          case 'V':
            EXTRACT_COLOR;
            sscanf(command + 1, "%d %d %d", &x, &y1, &y2);
            DRAW_VSEG;
            break;
          case 'H':
            EXTRACT_COLOR;
            sscanf(command + 1, "%d %d %d", &x1, &x2, &y);
            DRAW_HSEG;
            break;
          case 'K':
            EXTRACT_COLOR;
            sscanf(command + 1, "%d %d %d %d", &x1, &y1, &x2, &y2);
            FILL_RECT;
            break;
          case 'F':
            EXTRACT_COLOR;
            sscanf(command + 1, "%d %d", &x, &y);
            fill_region(canvas, cols, rows, x - 1, y - 1, c);
            break;
          case 'S':
            sscanf(command + 1, "%*[ \t] %[^ \t\r\n]", name);
            print(name, canvas, cols, rows);
            break;
          case 'X':
            return 0;
        }
      }
    }
    
    #define WHITE '0'
    
    char **init(int cols, int rows)
    {
      char **canvas;
      int k, sz = (cols + 1) * sizeof(char);
    
      canvas = (char **)malloc(rows * sizeof(char *));
      for (k = 0; k < rows; k++)
      {
        canvas[k] = (char *)malloc(sz);
        memset((void *)(canvas[k]), WHITE, sz);
        canvas[k][cols] = '\0';
      }
    
      return canvas;
    }
    
    void clear(char **canvas, int cols, int rows)
    {
      int k, sz = cols * sizeof(char);
    
      for (k = 0; k < rows; k++)
      {
        memset((void *)(canvas[k]), WHITE, sz);
        canvas[k][cols] = '\0';
      }
    }
    
    void empty(char **canvas, int cols, int rows)
    {
      int k;
    
      if (cols)
      {
        for (k = 0; k < rows; k++)
          free((void *)canvas[k]);
        free((void *)canvas);
      }
    }
    
    void print(char *name, char **canvas, int cols, int rows)
    {
      int k;
    
      printf("%s\n", name);
      for (k = 0; k < rows; k++)
      {
        canvas[k][cols] = '\0';
        printf("%s\n", canvas[k]);
      }
    }
    
    typedef struct {
      int x;
      int y;
    } COORDS;
    
    #define E_IN_THE_REGION (j = x + 1) < cols && canvas[y][j] == c0
    #define W_IN_THE_REGION (j = x - 1) >= 0 && canvas[y][j] == c0
    #define N_IN_THE_REGION (i = y - 1) >= 0 && canvas[i][x] == c0
    #define S_IN_THE_REGION (i = y + 1) < rows && canvas[i][x] == c0
    
    #define INCLUDE_IT(u, v) canvas[v][u] = color; newly_filled[w][count].x = u; newly_filled[w][count].y = v; count++;
    
    #define TRY_E if (E_IN_THE_REGION) {INCLUDE_IT(j, y);}
    #define TRY_W if (W_IN_THE_REGION) {INCLUDE_IT(j, y);}
    #define TRY_N if (N_IN_THE_REGION) {INCLUDE_IT(x, i);}
    #define TRY_S if (S_IN_THE_REGION) {INCLUDE_IT(x, i);}
    
    void fill_region(char **canvas, int cols, int rows, int x0, int y0, char color)
    {
      char c0 = canvas[y0][x0];
      int x, y, i, j, k, count, len, r = 1, w = 0, sz = cols * rows * sizeof(COORDS);
      COORDS **newly_filled;
    
      if (c0 != color)
      {
        canvas[y0][x0] = color;
    
        newly_filled = (COORDS **)malloc(2 * sizeof(COORDS *));
        newly_filled[0] = (COORDS *)malloc(sz);
        newly_filled[1] = (COORDS *)malloc(sz);
    
        newly_filled[w][0].x = x0;
        newly_filled[w][0].y = y0;
        count = 1;
        len = count;
        r = w;
        w = 1 - r;
    
        while (count)
        {
          for (k = 0, count = 0; k < len; k++)
          {
            x = newly_filled[r][k].x;
            y = newly_filled[r][k].y;
            TRY_E;
            TRY_W;
            TRY_N;
            TRY_S;
          }
          len = count;
          r = w;
          w = 1 - r;
        }
    
        free((void *)newly_filled[0]);
        free((void *)newly_filled[1]);
        free((void *)newly_filled);
      }
    }
    

    13년 전
3개의 댓글이 있습니다.
  • jspac
    jspac

    윽 죄송합니다..
    WHITE에 해당하는 문자가 숫자 0이 아니라 알파벳 대문자 'O'였네요 -_-;;;

    @ 근데 한 번 쓴 글은 못지우나요??? 창피해서 어쩌나..;;;


    13년 전 link
  • VOCList
    VOCList

    일단 알고리즘 트레이닝 북의 그래픽 에디터 문제라고만 써 놓으시면 도와드리고 싶어도 무슨 문젠지 아시는 분이 거의 없을거같네요.. 문제에 대해서 설명해주시는게 더 좋을것같습니다.


    13년 전 link
  • jspac
    jspac

    아, 죄송합니다, VOCList님..
    근데 위에 댓글처럼 숫자 0을 알파벳 O로 바꿔서 해결했네요..
    알고리즘이 문제가 아니라, 문제를 잘못 읽은 제가 문제였습니다;;;

    @어쨌든 문제 내용은 http://goo.gl/gs8Z3 에서 보실 수 있습니다.


    13년 전 link
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.