https://school.programmers.co.kr/learn/courses/30/lessons/17679
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
#include <string>
#include <vector>
using namespace std;
bool cal(int& answer, vector<string>& board)
{
vector<pair<int, int>> savePos;
vector<string> chB;
for (int i = 0; i < board.size(); i++)
{
string s = "";
for (int j = 0; j < board[i].length(); j++)
{
s += (board[i][j] == ' ') ? '0' : '1';
}
chB.push_back(s);
}
for (int i = 0; i < board.size() - 1; i++)
{
for (int j = 0; j < board[i].size() - 1; j++)
{
if (board[i][j] == ' ')continue;
if ((board[i][j] == board[i][j + 1]) && (board[i][j + 1] == board[i + 1][j]) &&
(board[i + 1][j] == board[i + 1][j + 1]))
{
// 4개 일치
for (int r = i; r <= i + 1; r++)
for (int c = j; c <= j + 1; c++)
if (chB[r][c] == '1') { answer++; chB[r][c] = '0'; }
savePos.push_back({ i,j });
}
}
}
if (savePos.size() == 0)return false;
for (auto item : savePos)
{
board[item.first][item.second] = ' ';
board[item.first][item.second + 1] = ' ';
board[item.first + 1][item.second] = ' ';
board[item.first + 1][item.second + 1] = ' ';
}
return true;
}
int solution(int m, int n, vector<string> board) {
int answer = 0;
while (cal(answer, board))
{
for (int i = 0; i < board[0].size(); i++)
{
for (int j = board.size()-1; j >=1 ; j--)
{
if (board[j][i] == ' ')
{
int k = j-1;
while (k >= 1 && board[k][i] == ' ')
k--;
if (k == 0 && board[k][i] == ' ')
continue;
board[j][i] = board[k][i];
board[k][i] = ' ';
}
}
}
}
return answer;
}
게임 기능을 만드는 문제인데 블록모양의 배열이 주어지고 각 원소는 대문자로 표시되어있다.
사각형의 4블록이 동일하면 사라지고 빈칸은 위에있던 블록이 메운다.
이 때, 한 블록은 여러 4블록에 사용이 가능하다.
알고리즘은 다음과 같다.
1. 한 블록이 중복되어 사용될 수 있기 때문에 사용됐던 것인지 체크하는 배열을 하나 만든다.
2. 4개가 동일한 경우를 찾는다.
3. 사용안됐던 블록은 카운트하고 사용처리한다.
4. 종료 후, 4개의 블록을 board에서 빈공간처리한다.
5. 빈공간을 다시 채운다. -> 1번으로 돌아간다.
1~3번은 cal이라는 함수로 만들어서 처리했다.
또 4~5번을 반복하기 위해선 solution 함수에서 while을 통해 처리한다.
bool cal(int& answer, vector<string>& board)
{
vector<pair<int, int>> savePos;
vector<string> chB;
for (int i = 0; i < board.size(); i++)
{
string s = "";
for (int j = 0; j < board[i].length(); j++)
{
s += (board[i][j] == ' ') ? '0' : '1';
}
chB.push_back(s);
}
for (int i = 0; i < board.size() - 1; i++)
{
for (int j = 0; j < board[i].size() - 1; j++)
{
if (board[i][j] == ' ')continue;
if ((board[i][j] == board[i][j + 1]) && (board[i][j + 1] == board[i + 1][j]) &&
(board[i + 1][j] == board[i + 1][j + 1]))
{
// 4개 일치
for (int r = i; r <= i + 1; r++)
for (int c = j; c <= j + 1; c++)
if (chB[r][c] == '1') { answer++; chB[r][c] = '0'; }
savePos.push_back({ i,j });
}
}
}
if (savePos.size() == 0)return false;
for (auto item : savePos)
{
board[item.first][item.second] = ' ';
board[item.first][item.second + 1] = ' ';
board[item.first + 1][item.second] = ' ';
board[item.first + 1][item.second + 1] = ' ';
}
return true;
}
cal 함수인데 bool 값을 리턴한다.
4개가 동일한 블록이 하나라도 있었으면 true 아니면 false이다.
먼저 chB배열이 사용됐었는지 체크하는 배열이다.(사용됐거나 빈칸이면 0 아니면 1이다.)
또 savePos는 기준점인 i,j 지점을 저장하는 역할이다.
for문에서 i,j 를 기준으로 오른쪽, 아래, 대각선을 확인하기 때문.
if ((board[i][j] == board[i][j + 1]) && (board[i][j + 1] == board[i + 1][j]) &&
(board[i + 1][j] == board[i + 1][j + 1]))
{
// 4개 일치
for (int r = i; r <= i + 1; r++)
for (int c = j; c <= j + 1; c++)
if (chB[r][c] == '1') { answer++; chB[r][c] = '0'; }
savePos.push_back({ i,j });
이중 for문을 돌며 4개가 일치하는 경우 각 칸에 대해서 사용됐던 것인지 판단하고 처리한다.
그리고 그 좌표를 savePos에 저장한다.
if (savePos.size() == 0)return false;
for (auto item : savePos)
{
board[item.first][item.second] = ' ';
board[item.first][item.second + 1] = ' ';
board[item.first + 1][item.second] = ' ';
board[item.first + 1][item.second + 1] = ' ';
}
return true;
모든 좌표를 살펴보고 저장된 좌표가 없다면 false리턴
아니면 savePos를 순회하면서 board를 빈공간으로 표시한다.
while (cal(answer, board))
{
for (int i = 0; i < board[0].size(); i++)
{
for (int j = board.size()-1; j >=1 ; j--)
{
if (board[j][i] == ' ')
{
int k = j-1;
while (k >= 1 && board[k][i] == ' ')
k--;
if (k == 0 && board[k][i] == ' ')
continue;
board[j][i] = board[k][i];
board[k][i] = ' ';
}
}
}
}
solution에서 while문을 통해 cal함수를 계속 호출한다.
리턴결과가 true면 바뀐결과가 있으므로 이중 for문을 통해 빈공간을 채우는 작업을 한다.
한 열씩 보면서 아래쪽부터 내려할 블록이 있으면 while문을 통해 쌓일 좌표까지 내린다.
'알고리즘 > 프로그래머스 2단계' 카테고리의 다른 글
프로그래머스 - [3차] 방금그곡 - C++ (0) | 2024.08.16 |
---|---|
프로그래머스 - 두 큐 합 같게 만들기 - C++ (0) | 2024.08.13 |
프로그래머스 - 수식 최대화 - C++ (0) | 2024.08.09 |
프로그래머스 - 문자열 압축 - C++ (0) | 2024.08.09 |
프로그래머스 - 메뉴 리뉴얼 - C++ (0) | 2024.08.09 |