Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Volatile
- java
- Google OAuth
- 일급 객체
- synchronized
- 일급 컬렉션
- Dependency Injection
- builder
- OAuth 2.0
- nestjs
- middleware
- factory
- Spring
- spring security
- lombok
Archives
- Today
- Total
HJW's IT Blog
[프로그래머스/C++] 퍼즐 조각 채우기 본문
https://school.programmers.co.kr/learn/courses/30/lessons/84021
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제 분석: 퍼즐 맞추기 문제
이 문제는 게임 보드의 빈 공간에 테이블 위의 퍼즐 조각을 규칙에 맞게 최대한 많이 채우는 문제입니다. 주어진 퍼즐 조각을 회전시켜 빈칸에 맞추되, 인접한 칸이 비어 있지 않아야 하며, 퍼즐 조각은 한 번에 하나씩만 채울 수 있습니다. 퍼즐 조각의 뒤집기는 허용되지 않습니다. 게임 보드와 퍼즐 테이블은 각각 1x1 크기의 정사각형 격자 모양입니다. 목표는 퍼즐 조각을 적절히 배치해 최대한 많은 칸을 채우는 것입니다.
제한 사항
- 게임 보드와 퍼즐 테이블은 정사각형이며, 크기는 최소 3x3, 최대 50x50입니다.
- 퍼즐 조각은 최소 1개에서 최대 6개까지 연결된 1x1 정사각형으로 이루어져 있습니다.
- 퍼즐 조각을 회전시킬 수 있지만, 뒤집을 수는 없습니다.
문제 풀이 접근법
- 퍼즐 조각 추출: 먼저 테이블 위의 퍼즐 조각을 추출합니다. bfs를 사용하여 퍼즐 조각의 모양을 추출하고, 이 모양을 회전할 수 있는 모든 경우의 수를 저장합니다.
- 게임 보드의 빈칸 추출: 같은 방식으로 게임 보드에서 비어 있는 공간의 모양을 추출합니다.
- 퍼즐 조각 회전 및 매칭: 추출한 퍼즐 조각을 회전시켜 게임 보드의 빈칸과 매칭합니다. 퍼즐 조각을 회전한 4가지 경우 중 하나가 빈칸의 모양과 일치하는지 확인합니다. 일치하면 해당 빈칸을 퍼즐 조각으로 채웁니다.
- 중복 체크 및 최댓값 계산: 퍼즐 조각을 한번 사용하면 다시 사용할 수 없으므로 중복 사용을 방지하고, 채운 퍼즐 칸 수를 누적해 최종 결과를 도출합니다.
코드 분석
퍼즐 조각 회전 함수
vector<vector<vector<int>>> rotate(vector<vector<int>> s){
vector<vector<vector<int>>> ans;
int n = s.size();
int m = s[0].size();
ans.push_back(s);
for(int k = 0; k < 3; k++) {
vector<vector<int>> ret(m, vector<int>(n, 0));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
ret[j][n - i - 1] = s[i][j];
}
}
s = ret;
ans.push_back(ret);
swap(n,m);
}
return ans;
}
이 함수는 주어진 퍼즐 조각을 90도씩 회전시켜 4가지 경우의 수를 반환합니다.
BFS를 통한 퍼즐 조각 추출
vector<vector<int>> bfsShape(vector<vector<int>>& table, int x, int y ,int num, vector<vector<bool>>& vis){
queue<pair<int,int>> q;
q.push({x,y});
int minX = x;
int maxX = x;
int minY = y;
int maxY = y;
vis[x][y] = true;
while(!q.empty()){
int cx = q.front().first;
int cy = q.front().second;
q.pop();
for(int i = 0; i<4; i++){
int nx = cx + dx[i];
int ny = cy + dy[i];
if(nx >= 0 && ny >= 0 && nx < table.size() && ny <table[0].size()){
if(!vis[nx][ny] && table[nx][ny] == num){
vis[nx][ny] = true;
q.push({nx,ny});
minX = min(minX, nx);
minY = min(minY, ny);
maxX = max(maxX, nx);
maxY = max(maxY, ny);
}
}
}
}
int vertical = abs(maxX - minX) + 1;
int horizontal = abs(maxY - minY) + 1;
vector<vector<int>> ret(vertical, vector<int>(horizontal, 0));
for(int i = minX; i<=maxX; i++){
int i2 = i - minX;
for(int j = minY; j<=maxY; j++){
int j2 = j - minY;
if(table[i][j] == num){
ret[i2][j2] = 1;
}
}
}
return ret;
}
이 함수는 BFS 탐색을 사용하여 테이블 위의 퍼즐 조각을 추출합니다. 추출된 조각은 최소 크기의 격자판으로 반환됩니다.
모양 비교 및 퍼즐 채우기
bool matchShape(vector<vector<int>>& emptyShape, vector<vector<int>>& shape) {
if (emptyShape.size() != shape.size() || emptyShape[0].size() != shape[0].size()) return false;
for (int i = 0; i < emptyShape.size(); i++) {
for (int j = 0; j < emptyShape[0].size(); j++) {
if (emptyShape[i][j] != shape[i][j]) return false;
}
}
return true;
}
이 함수는 빈칸의 모양과 퍼즐 조각의 모양이 일치하는지 확인합니다. 사이즈나 내용이 하나라도 다르면 false를 반환합니다.
solution 함수
int solution(vector<vector<int>> game_board, vector<vector<int>> table) {
int answer = 0;
vector<vector<vector<int>>> shapes;
vector<vector<vector<int>>> emptyShapes;
visited.resize(table.size(), vector<bool>(table[0].size(), false));
visited2.resize(table.size(), vector<bool>(table[0].size(), false));
for(int i = 0; i<table.size(); i++){
for(int j = 0; j<table[i].size(); j++){
if(!visited[i][j] && table[i][j] == 1){
shapes.push_back (bfsShape(table, i, j,1,visited));
}
}
}
for(int i = 0; i<table.size(); i++){
for(int j = 0; j<table[i].size(); j++){
if(!visited2[i][j] && game_board[i][j] == 0){
emptyShapes.push_back (bfsShape(game_board, i, j,0, visited2));
}
}
}
vector<bool> used(shapes.size(), false);
for(auto empty : emptyShapes){
bool matched = false;
for(int i = 0; i<shapes.size(); i++){
if(used[i]) continue;
auto rotations = rotate(shapes[i]);
for(auto rShape : rotations){
if(matchShape(empty, rShape)){
used[i] = true;
answer += countOnes(rShape);
matched = true;
break;
}
}
if(matched) break;
}
}
return answer;
}
'Algorithm' 카테고리의 다른 글
[프로그래머스/C++/ JAVA/ Javascript][PCCP 기출문제] 3번 / 충돌위험 찾기 (0) | 2024.09.12 |
---|---|
[프로그래머스/C++][PCCP 기출문제] 2번 / 퍼즐 게임 챌린지 (0) | 2024.09.12 |
[프로그래머스/C++] 순위 검색 (2) | 2024.09.10 |
[프로그래머스/C++] 괄호 회전하기 (0) | 2024.09.10 |
[프로그래머스/C++] 거리두기 확인하기 (0) | 2024.09.10 |