https://www.acmicpc.net/problem/20061
20061번: 모노미노도미노 2
모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는 형태이다. 게임에서 사용하는 좌표 (x, y)에서 x는 행,
www.acmicpc.net
소요 시간
골드 2 기준 1시간 정도 소요되었습니다. 골드 2 문제치고 크게 까다롭지 않은 문제였습니다.
구상
문제는 블록 놓기 - 점수 계산 - 0,1 줄 처리 의 과정을 따라야 합니다.
1. 블록 놓기
저의 경우 blue와 green을 서로 다른 배열에 상태관리하여, 각자 4x6 크기를 가지게 하였고 두 배열 모두 왼쪽 상단이 0,0이 되게끔 했습니다. 이렇게 하면 블록을 놓을 때, blue의 type 2 블록을 처리하는 방법이 green의 type 3 블록을 처리하는 방법이 되고, 반대도 마찬가지입니다. 또한, (3,0) 자리에 1칸짜리 블록이 놓인다면 green은 y좌표가 0이면서 가능한 가장 큰 x좌표를 갖는 자리에 블록이 배치될 것이고, blue는 y좌표가 3이면서 가능한 가장 큰 x좌표를 갖는 자리에 블록이 배치될 것입니다. 즉 y좌표로 green은 y좌표를 가져가고 blue는 x좌표를 가져가면서, 최대한 큰 x를 갖는 비어있는 좌표를 구하면 블록이 놓일 자리가 됩니다.
2. 점수 계산
전체 줄이 다 채워지면 배열에서 해당 줄을 지우고, 맨 앞에 0으로 가득찬 배열을 삽입하는 식으로 구현했습니다.
3. 0, 1 줄 처리
마찬가지로 0과 1 줄을 보고 1이 있는 줄의 개수만큼 배열의 마지막 줄을 지우고, 맨 앞에 0으로 가득찬 배열을 삽입하는 식으로 구현했습니다.
코드
#include <string>
#include <vector>
#include<iostream>
#include <climits>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
vector<vector<int> > green;
vector<vector<int> > blue;
void special_area() {
vector<int> add; add.resize(4);
int greencnt = 0; int bluecnt = 0;
for(int i = 0; i < 2; i++) {
for(int j=0; j<4; j++) {
if(green[i][j] == 1) {
greencnt += 1;
break;
}
}
for(int j=0; j<4; j++) {
if(blue[i][j] == 1) {
bluecnt += 1;
break;
}
}
}
while(greencnt > 0) {
greencnt --;
green.erase(green.end()-1);
green.insert(green.begin(), add);
}
while(bluecnt > 0) {
bluecnt --;
blue.erase(blue.end()-1);
blue.insert(blue.begin(), add);
}
}
int get_score() {
int score = 0;
bool greenFull[6]; bool blueFull[6];
fill_n(greenFull, 6, true);
fill_n(blueFull, 6, true);
for(int i=0; i<6; i++) {
//green
for(int j=0; j<4; j++) {
if(green[i][j] == 0) {
greenFull[i] = false; break;
}
}
//blue
for(int j=0; j<4; j++) {
if(blue[i][j] == 0) {
blueFull[i] = false; break;
}
}
}
//행 삭제
vector<int> add; add.resize(4);
for(int i=0; i<6; i++) {
if(greenFull[i]) {
green.erase(green.begin() + i);
green.insert(green.begin(), add);
score ++;
}
if(blueFull[i]) {
blue.erase(blue.begin() + i);
blue.insert(blue.begin(), add);
score ++;
}
}
return score;
}
void do_command(int t, int x, int y) {
//green
int nx = 0; int ny = y;
if(t == 1) {
while(nx < 6 && green[nx][ny] == 0) {
nx ++;
}
green[nx-1][ny] = 1;
}
else if(t == 2) {
while(nx < 6 && green[nx][ny] == 0 && green[nx][ny+1] == 0) {
nx ++;
}
green[nx-1][ny] = 1; green[nx-1][ny+1] = 1;
}
else if(t == 3) {
while(nx+1 < 6 && green[nx][ny] == 0 && green[nx+1][ny] == 0) {
nx ++;
}
green[nx-1][ny] = 1; green[nx][ny] = 1;
}
//blue
nx = 0; ny = x;
if(t == 1) {
while(nx < 6 && blue[nx][ny] == 0) {
nx ++;
}
blue[nx-1][ny] = 1;
}
else if(t == 3) {
while(nx < 6 && blue[nx][ny] == 0 && blue[nx][ny+1] == 0) {
nx ++;
}
blue[nx-1][ny] = 1; blue[nx-1][ny+1] = 1;
}
else if(t == 2) {
while(nx+1 < 6 && blue[nx][ny] == 0 && blue[nx+1][ny] == 0) {
nx ++;
}
blue[nx-1][ny] = 1; blue[nx][ny] = 1;
}
}
int main(int argc, char** argv)
{
ios_base :: sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int n;
cin >> n;
green.resize(6); blue.resize(6);
for(int i=0; i<6; i++) {
green[i].resize(4);
blue[i].resize(4);
}
int score = 0;
for(int i=0; i<n; i++) {
int t, x, y;
cin >> t >> x >> y;
do_command(t, x, y);
score += get_score();
special_area();
}
int cnt = 0;
for(int i=0; i<6; i++) {
for(int j=0; j<4; j++) {
if(green[i][j] == 1) cnt ++;
if(blue[i][j] == 1) cnt ++;
}
}
cout << score << "\n" << cnt << "\n";
return 0;
}
'PS문제들' 카테고리의 다른 글
[백준] 19238: 스타트 택시(C++) (0) | 2022.09.28 |
---|---|
[백준] 19236: 청소년 상어(C++) (0) | 2022.09.28 |
[백준] 17837: 새로운 게임 2(C++) (0) | 2022.09.27 |
[백준] 17822: 원판 돌리기(C++) (0) | 2022.09.27 |
[백준] 17142: 연구소 3(C++) (0) | 2022.09.26 |
댓글