ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [SWEA] 5653. 줄기세포배양
    문제 풀이 2020. 5. 9. 17:29

    5653 줄기세포배양


    풀이)


    처음에는 어떻게 좌표를 잡아야하는지 몰라서, 

    set 이용해서 이미 세포가 있는 곳은 번식하지 않게 했다.

    (세포는 struct sepo{}를 선언해서 관련 정보를 저장했고)

    그러다보니 통과는 했지만 시간이 어마 무시했다.


    set을 이용한 코드)


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    #include <stdio.h>
    #include <vector>
    #include <algorithm>
    #include <string.h>
    #include <set>
    using namespace std;
     
    set <pair<intint>>visited;
     
    int dy[4= { -1,1,0,0 };
    int dx[4= { 0,0,-1,1 };
    struct sepo {
        int y, x;
        int life; //생명력
        int time;
        bool active;
     
        sepo(int y, int x,int time, bool active) {
            this->= y;
            this->= x;
            this->life = time;
            this->time = time;
            this->active = active;
        }
     
    };
     
    bool cmp(const sepo &a, const sepo &b) {
        if (a.y == b.y && a.x == b.x) {
            return a.life > b.life;
        }
        if (a.x == b.x) {
            return a.y < b.y;
        }
        else {
            return a.x < b.x;
        }
    }
     
    int main() {
        //freopen("sample_input.txt", "r", stdin);
        int T = 0;
        scanf("%d"&T);
        for (int test_case = 1; test_case <= T; test_case++) {
            int n, m, k;
            scanf("%d %d %d"&n, &m, &k);
            vector<sepo> se;
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    int temp;
                    scanf("%d"&temp);
                    if (temp > 0) {
                        se.push_back({ i,j,temp,false });
                        visited.insert({ i,j });
                    }
                }
            }
            vector <sepo> temp;
            while (k--)
            {
                
                for (int i = 0; i < se.size(); i++) {
                    if (se[i].time == 0 && se[i].active==false)continue;
                    
                    if (se[i].active) {
                        if (se[i].life == se[i].time) {//맨처음 1시간
                            //번식일어남
                            for (int j = 0; j < 4; j++) {
                                int ny = se[i].y + dy[j];
                                int nx = se[i].x + dx[j];
                                if (visited.find({ ny,nx }) != visited.end())continue;//이미 하나의 줄기세포 존재
                                temp.push_back({ ny,nx,se[i].life,false });
                            }
                        }
                        se[i].time -= 1;
                        if (se[i].time == 0) {
                            se[i].active = false;//완전히 죽음
                        }
                        continue;
                    }
                    se[i].time -= 1;
                    if (se[i].time == 0 && se[i].active == false) {
                        se[i].active = true//활성화
                        se[i].time = se[i].life;
                        continue;
                    }
                    
                }
                if (temp.empty())continue;
                //예비번식자 중 하나의 그리드 셀에 동시 번식하려면 빼줌
                sort(temp.begin(), temp.end(), cmp); // 생명력내림차순
                for (int i = 0; i < temp.size(); i++) {
                    if (visited.find({temp[i].y,temp[i].x}) != visited.end())continue;
                    visited.insert({ temp[i].y,temp[i].x });
                    se.push_back(temp[i]);
                }
                temp.clear();
            }
            int result = 0;
            for (int i = 0; i < se.size(); i++) {
                if (se[i].time >0) result++;
            
            }
            printf("#%d %d\n", test_case, result);
            visited.clear();
        }
        return 0;
    }
    cs


    시간을 어떻게 줄이는 지 싶어 다른 분의 코드를 보니,

    왜 이 생각을 못했나 싶었다.

    "줄기 세포의 수명은 1~10년, 그리드는 1~50, 시간은 최대 300 이니깐

     최악의 경우를 생각했을 때

     수명이 1인 줄기 세포가 50*50 그리드를 꽉 채우고 있을 때인데

     그래봤자 2시간당 1칸밖에 안움직이니깐 최대로 가봤자 상하좌우 150칸이내이다"


    이 생각을 적용해서 이미 세포가 있음을 표시하는 visited를 이제는 set이 아니라

    배열로 선언해서 풀었다.

    그러니 시간이 2배넘게 절약되었다.


    배열을 이용한 코드)


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    #include <stdio.h>
    #include <vector>
    #include <algorithm>
    #include <string.h>
    #include <set>
    using namespace std;
     
    #define BASE 200
     
    int visited[500][500];
    int dy[4= { -1,1,0,0 };
    int dx[4= { 0,0,-1,1 };
    struct sepo {
        int y, x;
        int life;
        int time;
        bool active;
     
        sepo(int y, int x,int time, bool active) {
            this->= y;
            this->= x;
            this->life = time;
            this->time = time;
            this->active = active;
        }
     
    };
     
    bool cmp(const sepo &a, const sepo &b) {
        if (a.y == b.y && a.x == b.x) {
            return a.life > b.life;
        }
        if (a.x == b.x) {
            return a.y < b.y;
        }
        else {
            return a.x < b.x;
        }
    }
     
    int main() {
        //freopen("sample_input.txt", "r", stdin);
        int T = 0;
        scanf("%d"&T);
        for (int test_case = 1; test_case <= T; test_case++) {
            int n, m, k;
            scanf("%d %d %d"&n, &m, &k);
            vector<sepo> se;
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    int temp;
                    scanf("%d"&temp);
                    if (temp > 0) {
                        se.push_back({ i+BASE,j+BASE,temp,false });
                        visited[i + BASE][j + BASE] = true;
                    }
                }
            }
            vector <sepo> temp;
            while (k--)
            {
                
                for (int i = 0; i < se.size(); i++) {
                    if (se[i].time == 0 && se[i].active==false)continue;//이미 번식끝난아이
                    
                    if (se[i].active) {
                        if (se[i].life == se[i].time) {
                            //번식일어남
                            for (int j = 0; j < 4; j++) {
                                int ny = se[i].y + dy[j];
                                int nx = se[i].x + dx[j];
                                if (visited[ny][nx])continue;//이미 하나의 줄기세포 존재
                                temp.push_back({ ny,nx,se[i].life,false });
                            }
                        }
                        se[i].time -= 1;
                        if (se[i].time == 0) {
                            se[i].active = false;//완전히 죽음
                        }
                        continue;
                    }
                    se[i].time -= 1;
                    if (se[i].time == 0 && se[i].active == false) {
                        se[i].active = true//활성화
                        se[i].time = se[i].life;
                        continue;
                    }
                    
                }
                if (temp.empty())continue;
                //예비번식자 중 하나의 그리드 셀에 동시 번식하려면 빼줌
                sort(temp.begin(), temp.end(), cmp);
                for (int i = 0; i < temp.size(); i++) {
                    if (visited[temp[i].y][temp[i].x])continue;
                    visited[temp[i].y][temp[i].x] = true;
                    se.push_back(temp[i]);
                }
                temp.clear();
            }
            int result = 0;
            for (int i = 0; i < se.size(); i++) {
                if (se[i].time >0) result++;
            
            }
            printf("#%d %d\n", test_case, result);
            memset(visited, falsesizeof(visited));
        }
        return 0;
    }
    cs



    +이거 말고도 다른 방법을 사용하신 분이 없나 싶어 살피니깐

    queue를 배열로 선언해서 푸신 분도 있었다.

    세포가 번식할 때, 생명력 수치가 높은 세포가 우선순위를 갖는데

    이를 이용해서 queue를 생명력 순으로 나눴다.


    queue<pair<intint> > q[11]; 로 선언해, 


    생명력이 10인 줄기세포부터 번식 즉 q[10]에 들은 세포부터 

    번식시켜서 visited를 true로 바꿔놓는 방법이었다.

    '문제 풀이' 카테고리의 다른 글

    [SWEZ] 2383 점심 식사시간  (0) 2020.05.11
    [SWEA] 2117. 홈 방범 서비스  (0) 2020.05.09
    [SWEA] 1952. 수영장  (0) 2020.05.08
    [SWEA] 1953 탈주범 검거  (0) 2020.05.08
    [SWEA] 2382 미생물 격리  (0) 2020.05.07

    댓글

Designed by Tistory.