SwExpertAcademy의 미생물격리(2382) 문제이다.


[ 문제풀이 ]

1) Vector의 Index를 이용해서 상당히 많은 부분을 해결한 문제이다. 먼저 본인은 맵을 int형 자료를 관리하는 vector로

    2차원 맵을 만들어 주었다. 2차원으로 만들어준 이유는 여러개의 군집들이 모이는 경우에, 그 군집들의 번호를 저장해주기

    위해서였다.

    이 얘기를 하기 전에 먼저 본인은 미생물들의 군집을 관리하는 구조체를 하나 만들어 주었다.

    구조체에서 관리하는 변수로는 군집의 (x, y)좌표, 그 군집에 모여있는 미생물의 수, 군집이 향하는 방향, 군집의 상태

    (죽었는지 살았는지) 로 관리해 주었다.

    이 구조체를 자료형으로 갖는 vector를 또 하나 만들어 주었다. 처음 입력받을 때 모든 군집들의 정보를 vector에 담아 주었

    다. 또한 입력과 동시에 MAP vector에 그 인덱스 번호를 넣어주었다.

void Input()    // 입력받는 함수
{
    cin >> N >> M >> K;
    for (int i = 0; i < K; i++)
    {
        int x, y, n, d;
        cin >> x >> y >> n >> d;
        Bug Temp;
        Temp.x = x; Temp.y = y;
        Temp.Num = n; Temp.Dir = d;
        Temp.State = true;
        V.push_back(Temp);
       
        MAP[x][y].push_back(i);       

        // 해당 군집의 번호를 MAP에 push!
    }
}

  

2) 이후에는 M초가 될 때까지 움직이고 합치고 죽이는 과정을 반복해 주었다.

    먼저 움직이는 것부터 알아보자.

    군집들은 자기자신의 방향으로 한칸씩 이동하는데 본인은 정말 움직여 주기만했다. 뭐 테두리로 가거나, 합쳐지는 군집들

    고려하지 않고 움직여 주기만 했다. 단지, vector에 저장되어 있는 군집들의 (x, y)좌표를 바꿔주기만 하였고 맵의 상태만

    바꿔주었다.

    과정은 이렇다.

    1. 현재 군집이 존재하는 좌표들을 모두 없애준다.;

    2. 한칸씩 움직이면서 군집이 존재하는 좌표에 해당 군집의 번호를 넣어준다.

    말보다는 코드로 이해해보자.

void Move_Bug()
{
    for (int i = 0; i < V.size(); i++)
    {
        if (V[i].State == false) continue;

        MAP[V[i].x][V[i].y].clear();        // 먼저 기존의 상태 제거
    }

    for (int i = 0; i < V.size(); i++)
    {
        if (V[i].State == false) continue;

        V[i].x = V[i].x + dx[V[i].Dir];
        V[i].y = V[i].y + dy[V[i].Dir];
        MAP[V[i].x][V[i].y].push_back(i);    // 맵의 새로운 좌표에 Index번호 push
    }
}


     이렇게 움직이고 나면 어떻게 되있을까?? 아마 2개이상의 군집이 모인 좌표의 size는 1보다 클 것이다.

      또한 맵의 테두리로 가 있는 군집들이 있을 것이다. 이제 이것들을 처리해 보자.

      먼저 첫번째는 테두리에 있는 놈들이다.

      테두리에 있는 놈들은 미생물의 수가 절반으로 줄게된다. 이 과정에서 0마리가 되면 더이상 군집은 군집의 역할을

      하지 못하게된다. 그게 아니라면 방향이 반대방향으로 전환된다.

      우리는 Vector에 모든 군집들에 대한 정보가 저장되어 있으므로 수를 절반으로 감소시켜주면 되고

      죽게되는 군집들에 대해서는 State = false 로 바꿔주면된다. 사실 군집안에 미생물의 수가 0이 되면 죽는거라서 딱히

      State가 필요하지는 않은데 왜 만들어서 썻는지 모르겠다.

     

      중요한건 합치는 부분이다. 군집들이 한 곳에 합쳐졌다는 것을 우리는 어떻게 알 수 있을까??

      아마 (x, y)에 여러군집들이 합쳐졌다고 하면 MAP[x][y].size() 가 2 이상일 것이다. 따라서, 이 경우에 여기에 모인

      군집들 중에서 가장 많은 미생물들이 있는 곳을 찾아내서 그 수만 모두 합쳐주면 된다.

      그걸 어떻게 알아낼까..?? 이 부분 때문에 MAP[][]을 int형 vector로 선언해준 것이다.

      우리는 지금 (x, y)에 있는 군집들의 Index번호를 MAP[][]에 저장해주었다.

      즉, 예를들어서 MAP[x][y]의 size가 2이고 그 안에 데이터들을 보니 { 1, 2 }가 있다고 가정해보자.

      그렇다면 군집을 관리하는 벡터의 1번 인덱스와 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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include<iostream>
#include<vector>
#include<algorithm>
 
#define endl "\n"
#define MAX 100
using namespace std;
 
typedef struct
{
    int x;
    int y;
    int Num;
    int Dir;
    bool State;
}Bug;
 
int Answer;
int N, M, K;
vector<int> MAP[MAX][MAX];
vector<Bug> V;
 
int dx[] = { 0-1100 };
int dy[] = { 000-11 };
 
void Initialize()
{
    Answer = 0;
    V.clear();
    for (int i = 0; i < MAX; i++)
    {
        for (int j = 0; j < MAX; j++)
        {
            MAP[i][j].clear();
        }
    }
}
 
bool Standard(Bug A, Bug B)
{
    if (A.Num > B.Num) return true;
    return false;
}
 
void Input()
{
    cin >> N >> M >> K;
    for (int i = 0; i < K; i++)
    {
        int x, y, n, d;
        cin >> x >> y >> n >> d;
        Bug Temp;
        Temp.x = x; Temp.y = y;
        Temp.Num = n; Temp.Dir = d;
        Temp.State = true;
        V.push_back(Temp);
        
        MAP[x][y].push_back(i);
    }
}
 
void Move_Bug()
{
    for (int i = 0; i < V.size(); i++)
    {
        if (V[i].State == falsecontinue;
 
        MAP[V[i].x][V[i].y].clear();
    }
 
    for (int i = 0; i < V.size(); i++)
    {
        if (V[i].State == falsecontinue;
 
        V[i].x = V[i].x + dx[V[i].Dir];
        V[i].y = V[i].y + dy[V[i].Dir];
        MAP[V[i].x][V[i].y].push_back(i);
    }
}
 
int Change_Direction(int Cur_D)
{
    if (Cur_D == 1return 2;
    else if (Cur_D == 2return 1;
    else if (Cur_D == 3return 4;
    else if (Cur_D == 4return 3;
}
 
void Kill_And_Sum_Bug()
{
    // Kill
    for (int i = 0; i < V.size(); i++)
    {
        if (V[i].State == falsecontinue;
 
        int x = V[i].x;
        int y = V[i].y;
        int d = V[i].Dir;
 
        if (x == 0 || y == 0 || x == N - 1 || y == N - 1)
        {
            V[i].Num = V[i].Num / 2;
            V[i].Dir = Change_Direction(d);
        }
 
        if (V[i].Num == 0)
        {
            V[i].State = false;
        }
    }
 
    for (int i = 0; i < V.size(); i++)
    {
        if (V[i].State == falsecontinue;
 
        int x = V[i].x;
        int y = V[i].y;
 
        if (MAP[x][y].size() > 1)
        {
            int Sum = 0;
            int Biggest_Num = 0;
            int Select_Dir = 0;
            int Select_Idx = 0;
 
            for (int j = 0; j < MAP[x][y].size(); j++)
            {
                Sum = Sum + V[MAP[x][y][j]].Num;
                if (V[MAP[x][y][j]].Num > Biggest_Num)
                {
                    Biggest_Num = V[MAP[x][y][j]].Num;
                    Select_Dir = V[MAP[x][y][j]].Dir;
                    Select_Idx = MAP[x][y][j];
                }
                V[MAP[x][y][j]].State = false;
            }
 
            V[Select_Idx].Num = Sum;
            V[Select_Idx].Dir = Select_Dir;
            V[Select_Idx].State = true;
            MAP[x][y].clear();
            MAP[x][y].push_back(Select_Idx);
        }
    }
}
 
int Calculate()
{
    int Sum = 0;
    for (int i = 0; i < V.size(); i++)
    {
        if (V[i].State == falsecontinue;
        Sum = Sum + V[i].Num;
    }
    return Sum;
}
 
void Print()
{
    cout << "####################################" << endl;
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            cout << MAP[i][j].size() << " ";
        }
        cout << endl;
    }
    cout << "####################################" << endl;
}
 
void Solution()
{
    for (int i = 0; i < M; i++)
    {
        Move_Bug();
        Kill_And_Sum_Bug();
    }
 
    Answer = Calculate();
}
 
void Solve()
{
    int Tc; cin >> Tc;
    for (int T = 1; T <= Tc; T++)
    {
        Initialize();
        Input();
        Solution();
 
        cout << "#" << T << " " << Answer << endl;
    }
}
 
int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
 
    //freopen("Input.txt", "r", stdin);
    Solve();
 
    return 0;
}
cs

     











+ Recent posts