알고리즘/프로그래머스
프로그래머스 - 블록 이동하기
시나모온
2020. 9. 9. 03:03
문제 링크입니다 : programmers.co.kr/learn/courses/30/lessons/60063
코딩테스트 연습 - 블록 이동하기
[[0, 0, 0, 1, 1],[0, 0, 0, 1, 0],[0, 1, 0, 1, 1],[1, 1, 0, 0, 1],[0, 0, 0, 0, 0]] 7
programmers.co.kr
알고리즘 자체는 BFS로 굉장히 쉽다.
하지만 구현이 상당히 어렵기 때문에 시간이 꽤 오래 걸렸다...
실수를 줄인다면 시간을 3분의 1 이하로 줄일 수 있을 거 같은데... 실수를 줄이는 연습부터 해야겠다.
그림을 그리면서 하니까 실수가 조금 줄어드는 것 같다. 그림을 그리면서 실수를 줄이자.
#include <string>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;
const int dy[4] = {-1, 1, 0, 0};
const int dx[4] = {0, 0, -1, 1};
// 짝수 위, 홀수 아래
const int dy2[4] = {-1, 0, -1, 0};
const int dx2[4] = {0, 0, 1, 1};
// 짝수 왼쪽, 홀수 오른쪽
const int dy3[4] = {0, 0, 1, 1};
const int dx3[4] = {-1, 0, -1, 0};
int n;
vector<vector<vector<bool>>> visited;
bool isClear(vector<vector<int>>& board, int y, int x) {
if(y < 0 || y + 1 >= n || x < 0 || x + 1 >= n) return false;
for(int i = 0; i < 2; i++) {
for(int j = 0; j < 2; j++) {
if(board[y + i][x + j]) return false;
}
}
return true;
}
int bfs(vector<vector<int>>& board) {
// {{y, x}, isVer}
queue<pair<pair<int, int>, bool>> q;
q.push({{0, 0}, 0});
visited[0][0][0] = true;
int ret = 0;
while(!q.empty()) {
int qSize = q.size();
// cout << "qSize : " << qSize << endl;
for(int i = 0; i < qSize; i++) {
int cy = q.front().first.first;
int cx = q.front().first.second;
bool cver = q.front().second;
q.pop();
// cout << cy << ' ' << cx << ' ' << cver << " -- " << ret << endl;
if(cver) {
if(cy == n - 2 && cx == n - 1) return ret;
} else {
if(cy == n - 1 && cx == n - 2) return ret;
}
for(int dir = 0; dir < 4; dir++) {
int ny = cy + dy[dir];
int nx = cx + dx[dir];
if(cver) {
if(ny < 0 || ny + 1 >= n || nx < 0 || nx >= n) continue;
if(board[ny][nx] || board[ny + 1][nx]) continue;
} else {
if(ny < 0 || ny >= n || nx < 0 || nx + 1 >= n) continue;
if(board[ny][nx] || board[ny][nx + 1]) continue;
}
if(visited[ny][nx][cver]) continue;
visited[ny][nx][cver] = true;
q.push({{ny, nx}, cver});
}
if(cver) {
// 짝수는 위, 홀수는 아래
for(int dir = 0; dir < 4; dir++) {
int ny = cy + dy3[dir];
int nx = cx + dx3[dir];
if(dir <= 1) {
if(!isClear(board, ny, nx)) continue;
} else {
if(!isClear(board, ny - 1, nx)) continue;
}
if(visited[ny][nx][!cver]) continue;
visited[ny][nx][!cver] = true;
q.push({{ny, nx}, !cver});
}
} else {
// 짝수는 위, 홀수는 아래
for(int dir = 0; dir < 4; dir++) {
int ny = cy + dy2[dir];
int nx = cx + dx2[dir];
if(dir <= 1) {
if(!isClear(board, ny, nx)) continue;
} else {
if(!isClear(board, ny, nx - 1)) continue;
}
if(visited[ny][nx][!cver]) continue;
visited[ny][nx][!cver] = true;
q.push({{ny, nx}, !cver});
}
}
}
ret++;
}
return -1;
}
int solution(vector<vector<int>> board) {
int answer = 0;
n = board.size();
visited.assign(n, vector<vector<bool>>(n, vector<bool>(2, false)));
answer = bfs(board);
return answer;
}
개발 환경 : vscode
지적, 조언, 질문 환영입니다! 댓글 남겨주세요~