별다른 알고리즘 없이 그냥 구현 문제였다.
파란색보드와 초록색보드가 서로대칭이다 보니 6X4 모양의 보드 하나로 퉁치고 계산했다.
파란색보드에 입력할 때 빨간보드의x,y 좌표를 서로 바꾸어 주면 된다.
두 보드 모두 6X4로 사용하기 때문에 두개를 붙인 블럭은 가로방향일 때만 신경써주면 된다.
물론 입력을 받을 때 t=2 혹은 t=3 인경우에 대칭이동을 시켜주어야 한다.
블럭이 세로인경우는 t=1 이 2번 호출된다고 간주하고 입력을 받았다.
가로 블럭의 경우 입력으로 주어진 x,y와 그에 종속적으로 x,y+1까지 고려해야 한다.
y 와 y+1 중 높이가 더 높은 위치에 해당하도록 한다.
계산은 항상 x,y에서만 진행하도록 x,y+1의 블럭은 type=3으로 하여 자체적으로 높이 계산을 못하도록 했다. 항상 x,y 위치에서만 연산하고 그 결과에 따라다니도록 했다. x,y에서 y+1의 위치까지도 고려해주므로 계산 결과는 문제가 없다.
#include <iostream>
#include <vector>
using namespace std;
int min(int a, int b) { return a < b ? a : b; }
// 블럭들 가라앉히기
void setBlock(int type, int x, int y, vector<vector<int>>& board)
{
int newX = 5;
board[x][y] = 0;
for (int i=x+1; i<6; ++i)
{
if (board[i][y] == 0)
continue;
newX = i-1;
break;
}
if (type == 2)
{
board[x][y+1] = 0;
for (int i=x+1; i<6; ++i) // i의 시작 지점이 입력으로 받을 때와 블록이 사라져서 내려갈때가 다르다. 이건 입력부분에서 0으로 맞춰주면 될듯?
{
if (board[i][y+1] == 0)
continue;
newX = min(newX, i-1);
break;
}
}
board[newX][y] = type;
if (type == 2)
board[newX][y+1] = 3;
}
// 채워진 줄 찾고 삭제시키기
int checkRow(vector<vector<int>>& board)
{
int cnt = 0;
for (int row=0; row<6; ++row)
{
int cntZero = 0;
for (int i=0; i<4; ++i)
{
if (board[row][i] == 0)
++cntZero;
}
if (cntZero > 0)
continue;
for (int i=0; i<4; ++i)
board[row][i] = 0;
cnt += 1;
}
return cnt;
}
int main ()
{
cin.tie(0);
ios_base::sync_with_stdio(false);
int score = 0;
vector<vector<int>> blue = vector<vector<int>>(6, vector<int>(4));
vector<vector<int>> green = vector<vector<int>>(6, vector<int>(4));
int n; cin >> n;
while (n--)
{
int t, x, y;
cin >> t >> x >> y;
switch(t)
{
case(1):
setBlock(1, 0, y, green);
setBlock(1, 0, x, blue);
break;
case(2):
setBlock(2, 0, y, green);
setBlock(1, 0, x, blue); // 혹시 몰라서 아래에 있는 블록 먼저 떨구기
setBlock(1, 0, x, blue);
break;
case(3):
setBlock(1, 0, y, green);
setBlock(1, 0, y, green);
setBlock(2, 0, x, blue);
break;
}
// 줄 채운거 삭제 시키고 밑으로 내리기
while (true)
{
int temp = checkRow(green);
if (temp == 0)
break;
score += temp;
for (int i=5; i>= 0; --i) // 아랫줄부터 처리해야 한다.
for (int j=0; j<4; ++j)
if (green[i][j] == 1 || green[i][j] == 2)
setBlock(green[i][j], i, j, green);
}
while (true)
{
int temp = checkRow(blue);
if (temp == 0)
break;
score += temp;
for (int i=5; i>=0; --i)
for (int j=0; j<4; ++j)
if (blue[i][j] == 1 || blue[i][j] == 2)
setBlock(blue[i][j], i, j, blue);
}
// 0, 1 초과분 밀어넣기
for (int qq = 0; qq < 2; ++qq)
for (int i=0; i<4; ++i)
{
if (green[1][i] != 0)
{
for (int r=5; r>=1; --r)
{
for (int c=0; c<4; ++c)
{
green[r][c] = green[r-1][c];
}
}
for (int c=0; c<4; ++c)
green[0][c] = 0;
break;
}
}
for (int qq = 0; qq < 2; ++qq)
for (int i=0; i<4; ++i)
{
if (blue[1][i] != 0)
{
for (int r=5; r>=1; --r)
{
for (int c=0; c<4; ++c)
{
blue[r][c] = blue[r-1][c];
}
}
for (int c=0; c<4; ++c)
blue[0][c] = 0;
break;
}
}
}
// 남아있는거 계산
int left = 0;
for (int i=0; i<6; ++i)
{
for (int j=0; j<6; ++j)
{
if (green[i][j] != 0)
++left;
if (blue[i][j] != 0)
++left;
}
}
cout << score << endl;
cout << left << endl;
return 0;
}