https://www.acmicpc.net/problem/20061

 

20061번: 모노미노도미노 2

모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는 형태이다. 게임에서 사용하는 좌표 (x, y)에서 x는 행,

www.acmicpc.net

생각보다 까다로운 문제.

크게 4가지  함수로 구현했다.

하나는 block_add , 그 다음은 check_point, 그 다음은 연한색 영역인 check_soft, 그 다음은 블록 행또는 열을 지워주는
down_block_point_or_disappear 함수.

1
2
3
4
5
6
7
#include <iostream>
#include <deque>
using namespace std;
int map[10][10];
int N, T, X, Y;
int block[4][2= { {0,0},{0,0},{0,1},{1,0} };
int total_result = 0;
cs

다음과 같이 변수들을 전역으로 사용했다.

map는 그냥 10*10이다. 초록색 파란색을 따로 선언할까 하는 생각을 했지만, 이게 더 편한거같다. 간편하게 행과 열만 바꿔서 생각하면된다.
block은 다음과 같이 한 이유는 이따가 설명, 뭐 대충보면 두개인 경우 한개 인 경우가 있으므로 저렇게 한 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void solve() {
    cin >> N;
    for (int i = 0; i < N; i++) {
        cin >> T >> X >> Y;
        block_add();
        check_point();
        check_soft();
    }
    cout << total_result << endl;
    int count = 0;
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            if (map[i][j] == 1)
                count++;
        }
    }
    cout << count << endl;
}
cs

solve함수 이다. 입력과 동시에 block_add, check_point, check_soft가 작동한다.
block_add함수는 다음과 같다.

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
void block_add() {
    int x1 = X;
    int x2 = X + block[T][0];
    int y1 = Y;
    int y2 = Y + block[T][1];
    while (1) {
        if (x1 == 10 || x2 == 10) {
            x1--, x2--;
            break;
        }
        if (map[x1][y1] == 1 || map[x2][y2] == 1) {
            x1--, x2--;
            break;
        }
        else {
            x1++, x2++;
        }
    }
    map[x1][y1] = 1; map[x2][y2] = 1;
    x1 = X;
    x2 = X + block[T][0];
    y1 = Y;
    y2 = Y + block[T][1];
    while (1) {
        if (y1 == 10 || y2 == 10) {
            y1--, y2--;
            break;
        }
        if (map[x1][y1] == 1 || map[x2][y2] == 1) {
            y1--, y2--;
            break;
        }
        else {
            y1++, y2++;
        }
    }
    map[x1][y1] = 1; map[x2][y2] = 1;
}
cs

block_add 함수 이다. 이름과 같이 block을 추가하는 함수.
블럭은 많아도 좌표가 두개이다. 그러므로 다음과 같이 구현했다.
입력 받은(x,y), (x+dx[type][0], y+dy[type][1]) 이다. 
블럭이 내려가는 과정은 중력과 같다. 그냥 두개의 x1,x2좌표, 또는 y1,y2좌표의 map칸이 1이 아니고, 9이하이면 된다.

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
void check_point() {
    for (int i = 6; i <= 9; i++) {
        int count = 0;
        for (int j = 0; j < 4; j++) {
            if (map[i][j] == 1)
                count++;
        }
        if (count == 4) {
            for (int j = 0; j < 4; j++) {
                map[i][j] = 0;
            }
            total_result++;
            down_block_point_or_disappear(i, 1);
        }
    }
    for (int j = 6; j <= 9; j++) {
        int count= 0;
        for (int i = 0; i < 4; i++) {
            if (map[i][j] == 1)
                count++;
        }
        if (count == 4) {
            for (int i = 0; i < 4; i++) {
                map[i][j] = 0;
            }
            total_result++;
            down_block_point_or_disappear(j, 0);
        }
    }
}
cs

포인트를 얻는 과정, 여기선 그냥 연한칸을 제외하고 행과 열에서 1이 4개인 것을 count해서 이 행을 0으로 만든  뒤에 점수를 1점 더해주면된다.
그리고 블록이 위에서 내려오는 과정은 down_block_point_or_disappear로 구현했다.
0이면 푸른색, 1이면 초록색이다.

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
void down_block_point_or_disappear(int index, int line) { // line 0 이면 블루, 1 이면 그린
    deque<int> dq;
    if (line == 1) {
        for (int i = 4; i <= index - 1; i++) {
            for (int j = 0; j < 4; j++) {
                dq.push_back(map[i][j]);
                map[i][j] = 0;
            }
        }
        for (int i = 5; i <= index; i++) {
            for (int j = 0; j < 4; j++) {
                map[i][j] = dq.front();
                dq.pop_front();
            }
        }
    }
    else {
        for (int j = 4; j <= index - 1; j++) {
            for (int i = 0; i < 4; i++) {
                dq.push_back(map[i][j]);
                map[i][j] = 0;
            }
        }
        for (int j = 5; j <= index; j++) {
            for (int i = 0; i < 4; i++) {
                map[i][j] = dq.front();
                dq.pop_front();
            }
        }
    }
}
cs

이 함수는 대충 이런느낌이다. 포인트를 얻거나, 연한색에서 사라지면 위에줄을 한줄 내리는 방식,
dq에 순서를 맞춰서 넣은 다음에, 아래쪽 줄로 한줄 내려서 넣는다.

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
void check_soft() {
    int count = 0;
    for (int i = 4; i < 6; i++) {
        for (int j = 0; j < 4; j++) {
            if (map[i][j] == 1) {
                count++;
                break;
            }
        }
    }
    for (int i = 0; i < count; i++) {
        down_block_point_or_disappear(91);
    }
    count = 0;
    for (int j = 4; j < 6; j++) {
        for (int i = 0; i < 4; i++) {
            if (map[i][j] == 1) {
                count++;
                break;
            }
        }
    }
    for (int i = 0; i < count; i++
        down_block_point_or_disappear(90);
}
cs

check soft함수 연한색에 블럭이 있으면, 맨 아래 행이나 열을 삭제한다.
맨 아래 행이나 열 이므로 9가 들어간다.
전체 코드는 다음과 같다.

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
#include <iostream>
#include <deque>
using namespace std;
int map[10][10];
int N, T, X, Y;
int block[4][2= { {0,0},{0,0},{0,1},{1,0} };
int total_result = 0;
void print() {
    cout << "green" << endl;
    for (int i = 4; i <= 9; i++) {
        for (int j = 0; j < 4; j++) {
            cout << map[i][j] << " ";
        }
        cout << endl;
    }
    cout << endl;
    cout << "blue" << endl;
    for (int i = 0; i < 4; i++) {
        for (int j = 4; j <= 9; j++) {
            cout << map[i][j] << " ";
        }
        cout << endl;
    }
    cout << endl;
}
void down_block_point_or_disappear(int index, int line) { // line 0 이면 블루, 1 이면 그린
    deque<int> dq;
    if (line == 1) {
        for (int i = 4; i <= index - 1; i++) {
            for (int j = 0; j < 4; j++) {
                dq.push_back(map[i][j]);
                map[i][j] = 0;
            }
        }
        for (int i = 5; i <= index; i++) {
            for (int j = 0; j < 4; j++) {
                map[i][j] = dq.front();
                dq.pop_front();
            }
        }
    }
    else {
        for (int j = 4; j <= index - 1; j++) {
            for (int i = 0; i < 4; i++) {
                dq.push_back(map[i][j]);
                map[i][j] = 0;
            }
        }
        for (int j = 5; j <= index; j++) {
            for (int i = 0; i < 4; i++) {
                map[i][j] = dq.front();
                dq.pop_front();
            }
        }
    }
}
void check_soft() {
    int count = 0;
    for (int i = 4; i < 6; i++) {
        for (int j = 0; j < 4; j++) {
            if (map[i][j] == 1) {
                count++;
                break;
            }
        }
    }
    for (int i = 0; i < count; i++) {
        down_block_point_or_disappear(91);
    }
    count = 0;
    for (int j = 4; j < 6; j++) {
        for (int i = 0; i < 4; i++) {
            if (map[i][j] == 1) {
                count++;
                break;
            }
        }
    }
    for (int i = 0; i < count; i++
        down_block_point_or_disappear(90);
}
void check_point() {
    for (int i = 6; i <= 9; i++) {
        int count = 0;
        for (int j = 0; j < 4; j++) {
            if (map[i][j] == 1)
                count++;
        }
        if (count == 4) {
            for (int j = 0; j < 4; j++) {
                map[i][j] = 0;
            }
            total_result++;
            down_block_point_or_disappear(i, 1);
        }
    }
    for (int j = 6; j <= 9; j++) {
        int count= 0;
        for (int i = 0; i < 4; i++) {
            if (map[i][j] == 1)
                count++;
        }
        if (count == 4) {
            for (int i = 0; i < 4; i++) {
                map[i][j] = 0;
            }
            total_result++;
            down_block_point_or_disappear(j, 0);
        }
    }
}
void block_add() {
    int x1 = X;
    int x2 = X + block[T][0];
    int y1 = Y;
    int y2 = Y + block[T][1];
    while (1) {
        if (x1 == 10 || x2 == 10) {
            x1--, x2--;
            break;
        }
        if (map[x1][y1] == 1 || map[x2][y2] == 1) {
            x1--, x2--;
            break;
        }
        else {
            x1++, x2++;
        }
    }
    map[x1][y1] = 1; map[x2][y2] = 1;
    x1 = X;
    x2 = X + block[T][0];
    y1 = Y;
    y2 = Y + block[T][1];
    while (1) {
        if (y1 == 10 || y2 == 10) {
            y1--, y2--;
            break;
        }
        if (map[x1][y1] == 1 || map[x2][y2] == 1) {
            y1--, y2--;
            break;
        }
        else {
            y1++, y2++;
        }
    }
    map[x1][y1] = 1; map[x2][y2] = 1;
}
void solve() {
    cin >> N;
    for (int i = 0; i < N; i++) {
        cin >> T >> X >> Y;
        block_add();
        check_point();
        check_soft();
    }
    cout << total_result << endl;
    int count = 0;
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            if (map[i][j] == 1)
                count++;
        }
    }
    cout << count << endl;
}
void init() {
    ios::sync_with_stdio(false);
    cin.tie(0);
}
int main() {
    init();
    solve();
}
cs

+ Recent posts