어흥
[백준 20061] 모노미노도미노 2 (C++) 본문
728x90
반응형
문제 링크: www.acmicpc.net/problem/20061
1. 주의할 점
- 모든 절차에 따른 함수를 정확히 구현해야 한다
- 연한색에 위치함으로 인해 사라지는 열/행은 점수에 반영되지 않는다
2. 구현
- 입력에 대해 블록을 V 벡터에 구조체 형태로 저장한다
- MV(0) ->Pop_down() -> MV(1) -> Pop_right() 함수가 한 사이클이다
- MV(0)을 통해 V에 저장된 형태의 블록을 아래로 내려서 Arr[][] 배열에 저장한다
- Pop_down() 함수를 통해 한 행에 4개가 쌓여 있는지 확인하며, 쌓여있다면 쌓인 행만큼 Result에 더하고 내린다. 이후, 연한색에 블록이 있는지 확인하며 있으면 차지하는 행만큼 위에서 아래로 내린다
- MV(1)을 통해 V에 저장된 형태의 블록을 오른쪽으로 움직여서 Arr[][] 배열에 저장한다
- Pop_right() 함수를 통해 한 열에 4개가 쌓여 있는지 확인하며, 쌓여있다면 쌓인 열만큼 Result에 더하고 오른쪽으로 민다. 이후, 연한색에 블록이 있는지 확인하며 있으면 차지하는 오른쪽으로 민다
- Cal() 함수를 통해 몇개의 블록이 남아있는지 확인한다
//이전 코드
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct info {
int y, x;
};
info tmp;
bool arr[13][13];
vector<info> v;
int dx[2] = { 0,1 }; //아래,오른쪽으로 이동
int dy[2] = { 1,0 };
int result = 0; //얻은 점수
int cal() {
int cnt = 0;
for (int i = 6; i < 10; i++)
for (int j = 0; j < 4; j++)
if (arr[i][j]) cnt++;
for (int x = 6; x < 10; x++)
for (int y = 0; y < 4; y++)
if (arr[y][x]) cnt++;
return cnt;
}
void pop_right() {
int cnt = 0, idx = 9;
for (int x = 9; x >= 6; x--) {
bool canPop = true;
for (int y = 0; y < 4; y++) {
if (!arr[y][x]) {
canPop = false;
break;
}
}
if (canPop) {
idx = min(idx, x);
cnt++;
for (int y = 0; y < 4; y++)
arr[y][x] = false;
}
}
if (cnt) {
for (int x = idx - 1; x >= 4; x--) {
for (int y = 0; y < 4; y++) {
arr[y][x + cnt] = arr[y][x];
arr[y][x] = false;
}
}
}
result += cnt;
cnt = 0;
for (int x = 4; x <= 5; x++) {
bool avail = false;
for (int y = 0; y < 4; y++) {
if (arr[y][x]) {
avail = true;
break;
}
}
if (avail) cnt++;
}
if (cnt) {
for (int x = 9; x >= 4; x--) {
for (int y = 0; y < 4; y++) {
arr[y][x + cnt] = arr[y][x];
arr[y][x] = false;
}
}
}
}
void pop_down() {
int cnt = 0, idx = 9;
for (int y = 9; y >= 6; y--) {
bool canPop = true;
for (int x = 0; x < 4; x++) {
if (!arr[y][x]) {
canPop = false;
break;
}
}
if (canPop) {
idx = min(idx, y);
cnt++;
for (int x = 0; x < 4; x++)
arr[y][x] = false;
}
}
if (cnt) { //삭제할 행이 존재한다면
for (int y = idx - 1; y >= 4; y--) {
for (int x = 0; x < 4; x++) {
arr[y + cnt][x] = arr[y][x];
arr[y][x] = false;
}
}
}
result += cnt;
cnt = 0;
for (int y = 4; y <= 5; y++) {
bool avail = false;
for (int x = 0; x < 4; x++) {
if (arr[y][x]) {
avail = true;
break;
}
}
if (avail) cnt++;
}
if (cnt) {
for (int y = 9; y >= 4; y--) {
for (int x = 0; x < 4; x++) {
arr[y + cnt][x] = arr[y][x];
arr[y][x] = false;
}
}
}
}
void mv(int dir) {
int m_len = 9;
for (int k = 0; k < v.size(); k++) {
int cx = v[k].x;
int cy = v[k].y;
int len = 0;
while (1) {
cy += dy[dir];
cx += dx[dir];
len++;
if (cx == 10 || cy == 10 || arr[cy][cx]) {
len--;
break;
}
}
m_len = min(m_len, len);
}
for (int k = 0; k < v.size(); k++) {
int cx = v[k].x + dx[dir] * m_len;
int cy = v[k].y + dy[dir] * m_len;
arr[cy][cx] = true;
}
if (dir == 0) pop_down();
else pop_right();
}
int main() {
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
int query, order, x, y;
cin >> query;
for (int t = 0; t < query; t++) {
cin >> order >> y >> x;
v.clear();
v.push_back({ y,x });
if (order == 2) v.push_back({ y,x + 1 });
else if (order == 3) v.push_back({ y + 1,x });
mv(0);
mv(1);
}
cout << result << '\n' << cal();
return 0;
}
//최근 코드 - 2021.04.22
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct info {
int y, x;
};
info tmp;
bool arr[11][11] = { false, };
int num, t, x, y, result = 0, tot = 0;
vector<info> v;
//하,우
int dx[2] = { 0,1 };
int dy[2] = { 1,0 };
void cal() {
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
if (arr[i][j])
tot++;
}
void goDown(int start, int mini, int cnt){
for (int i = start; i >= mini + cnt; i--) {
for (int j = 0; j < 4; j++) {
arr[i][j] = arr[i - cnt][j];
}
}
for (int i = mini; i < mini + cnt; i++)
for (int j = 0; j < 4; j++)
arr[i][j] = false;
}
void goRight(int start, int mini, int cnt) {
for (int j = start; j >= mini + cnt; j--) {
for (int i = 0; i < 4; i++) {
arr[i][j] = arr[i][j - cnt];
}
}
for (int j = mini; j < mini + cnt; j++)
for (int i = 0; i < 4; i++)
arr[i][j] = false;
}
void blur() {
//아래
int cnt = 0;
for (int i = 4; i < 6; i++) {
bool block = false;
for (int k = 0; k < 4; k++) {
if (arr[i][k]) {
block = true;
break;
}
}
if (block) cnt++;
}
if (cnt) goDown(9, 4, cnt);
//우
cnt = 0;
for (int j = 4; j < 6; j++) {
bool block = false;
for (int k = 0; k < 4; k++) {
if (arr[k][j]) {
block = true;
break;
}
}
if (block) cnt++;
}
if (cnt) goRight(9, 4, cnt);
}
void rmv() {
//아래
int cnt = 0, idx;
for (int i = 6; i <10; i++) {
int allFilled = true;
for (int j = 0; j < 4; j++) {
if (!arr[i][j]) {
allFilled = false;
break;
}
}
if (allFilled) {
cnt++;
idx = i;
}
}
if (cnt) {
goDown(idx, 4, cnt);
result += cnt;
}
cnt = 0;
for (int j = 6; j < 10; j++) {
int allFilled = true;
for (int i = 0; i < 4; i++) {
if (!arr[i][j]) {
allFilled = false;
break;
}
}
if (allFilled) {
cnt++;
idx = j;
}
}
if (cnt) {
goRight(idx, 4, cnt);
result += cnt;
}
}
void mv() {
for (int cd = 0; cd < 2; cd++) {
int lowest = 11;
for (int k = 0; k < v.size(); k++) {
int cy = v[k].y;
int cx = v[k].x;
int i = 0; //내려갈 수 있는 칸 수
while (++i) {
cy += dy[cd];
cx += dx[cd];
if (arr[cy][cx]) {
lowest = min(lowest, i - 1);
break;
}
}
}
for (int k = 0; k < v.size(); k++) {
int ny = v[k].y + (dy[cd] * lowest);
int nx = v[k].x + (dx[cd] * lowest);
arr[ny][nx] = true;
}
}
}
int main() {
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
cin >> num;
for (int i = 0; i < 4; i++) {
arr[10][i] = true;
arr[i][10] = true;
}
for (int i = 0; i < num; i++) {
cin >> t >> y >> x;
v.clear();
v.push_back({ y,x });
if (t == 2) v.push_back({ y,x + 1 });
else if (t == 3) v.push_back({ y + 1,x });
mv();
rmv();
blur();
}
cal();
cout << result << '\n' << tot;
return 0;
}
728x90
반응형
'알고리즘 > 백준' 카테고리의 다른 글
[백준 15809] 전국시대 (C++) (0) | 2021.03.11 |
---|---|
[백준 2922] 즐거운 단어 (C++) (0) | 2021.03.09 |
[백준 1561] 놀이 공원 (C++) (3) | 2021.02.25 |
[백준 3745] 오름세 (C++) (0) | 2021.02.25 |
[백준 3649] 로봇 프로젝트 (C++) (0) | 2021.02.25 |
Comments