알고리즘/백준
BOJ 4991 로봇 청소기/ C++
내이름은 킹햄찌
2022. 5. 23. 00:50
https://www.acmicpc.net/problem/4991
4991번: 로봇 청소기
각각의 테스트 케이스마다 더러운 칸을 모두 깨끗한 칸으로 바꾸는 이동 횟수의 최솟값을 한 줄에 하나씩 출력한다. 만약, 방문할 수 없는 더러운 칸이 존재하는 경우에는 -1을 출력한다.
www.acmicpc.net
백준 온라인저지 4991번 로봇 청소기문제입니다.
아이디어
더러운 칸이 최대 10개이기 때문에 더러운칸을 비트마스킹을 사용할 수 있게 숫자로 저장하고, 모든 더러운칸을 방문했을때 최소거리를 구하기 위해 bfs를 이용하여 완전탐색 하였습니다.
풀이 도중 더러운칸을 비트로 나타낸 state가 변경되었을때 newState를 사용하지 않아 고생을 좀 했네요
#include <iostream>
#include <queue>
#include<cstring>
#define MAX 21
using namespace std;
int room[MAX][MAX];
int cleanCnt[MAX][MAX][(1 << 11)];
int dy[4] = { 0,0,1,-1 };
int dx[4] = { 1,-1,0,0 };
int cnt;
int n, m;
struct point
{
int x = 0;
int y = 0;
};
point startPoint;
void bfs() {
queue < pair < pair<int, int> ,int> >q;
q.push({ { startPoint.y, startPoint.x },{0} });
cleanCnt[startPoint.y][startPoint.x][0] = 1;
while (!q.empty()) {
int y = q.front().first.first;
int x = q.front().first.second;
int state = q.front().second;
q.pop();
for (int i = 0; i < 4; i++) {
int ny = y + dy[i];
int nx = x + dx[i];
//범위 체크
if (ny >= n || ny < 0 || nx >= m || nx < 0) continue;
if (room[ny][nx] < 0) continue;
//더러운 곳일때
if (room[ny][nx]>0) {
int newState = state | (1 << (room[ny][nx]-1));
//더러운곳이 없다면
if (newState == ((1 << cnt) - 1)) {
cout<< cleanCnt[y][x][state]<<"\n";
return;
}
if (cleanCnt[ny][nx][newState]) continue;
cleanCnt[ny][nx][newState] = cleanCnt[y][x][state] + 1;
q.push({ {ny, nx}, newState} );
}
if (cleanCnt[ny][nx][state]) continue;
cleanCnt[ny][nx][state] = cleanCnt[y][x][state] + 1;
q.push({ {ny, nx}, state });
}
}
cout << -1 << "\n";
}
void solution() {
while (true) {
cin >> m >> n;
if (n == 0 && m == 0) break;
cnt = 0;
memset(cleanCnt, 0, sizeof(cleanCnt));
memset(room, 0, sizeof(room));
char c;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> c;
if (c == '*')
room[i][j] = ++cnt;
else if (c == 'x')
room[i][j] = -1;
else if (c == 'o') {
startPoint.y = i;
startPoint.x = j;
room[i][j] = 0;
}
else
room[i][j] = 0;
}
}
bfs();
}
}
int main(void) {
solution();
}