알고리즘문제풀이/백준
[BOJ]4991_로봇 청소기_Java
초보개발자..
2021. 5. 17. 21:18
--문제--
https://www.acmicpc.net/problem/4991
4991번: 로봇 청소기
각각의 테스트 케이스마다 더러운 칸을 모두 깨끗한 칸으로 바꾸는 이동 횟수의 최솟값을 한 줄에 하나씩 출력한다. 만약, 방문할 수 없는 더러운 칸이 존재하는 경우에는 -1을 출력한다.
www.acmicpc.net
--문제접근--
처음에 접근하기를
DFS로 먼지갯수를 샌이후에 순열을 하는 과정을 생각했지만 구현능력이 부족하여 조금 더 다른 방법을 생각했습니다.
그러면서 생각했던 방법이 BOJ_1194문제와 같은 방식으로 생각을 하게되었는데 비트마스킹을 이용하여 문제를 접근하는 것이였습니다.
visit배열을 3차원boolean배열을 만든 이후에 비트마스킹을 통하여 방문하였는지 안하였는지 판단하여 체크하는 방식으로 진행합니다.
package 백준문제풀이;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class BOJ_4991로봇청소기 {
static class point{
int x,y,dist,cnt;
public point(int x, int y, int dist, int cnt) {
super();
this.x = x;
this.y = y;
this.dist = dist;
this.cnt = cnt;
}
}
static int[] dr= {-1,1,0,0};
static int[] dc= {0,0,1,-1};
static int row,column,cnt,ans;
static char[][] map;
static boolean[][][] visit;
static Queue<point> queue ;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while(true) {
column=sc.nextInt();
row=sc.nextInt();
if(row==0&&column==0)break;
cnt=0;
int dx=0;
int dy=0;
map=new char[row][column];
for(int i=0;i<row;i++) {
String str=sc.next();
for(int j=0;j<column;j++) {
map[i][j]=str.charAt(j);
if(map[i][j]=='*') {
map[i][j]=(char)(cnt+'0');
cnt++;
};
if(map[i][j]=='o') {
dx=i;dy=j;
map[i][j]='.';
}
}
}
visit=new boolean[row][column][1<<cnt];
ans=Integer.MAX_VALUE;
queue=new LinkedList<point>();
queue.offer(new point(dx,dy,0,0));
BFS();
if(ans==Integer.MAX_VALUE) {
System.out.println(-1);
}
else {
System.out.println(ans);
}
}
}
private static void BFS() {
//이과정은 비트마스킹을 통해 bfs를 돌면서 확인을 하는과정이다.
while(!queue.isEmpty()) {
point curr=queue.poll();
// System.out.println(curr.x+" "+curr.y+" "+row+" "+column);
visit[curr.x][curr.y][0]=true;
if(curr.cnt==(1<<cnt)-1) {
ans=curr.dist;
break;
}
for(int d=0;d<4;d++) {
int nr=curr.x+dr[d];
int nc=curr.y+dc[d];
if(nr>=0&&nc>=0&&nr<row&&nc<column&&!visit[nr][nc][curr.cnt]&&map[nr][nc]!='x') {
//이동할수있는경우
if('0'<=map[nr][nc]&&map[nr][nc]<='9') {
int newcnt=curr.cnt|(int)Math.pow(2,(map[nr][nc]-'0'));// or을 통해 축적해나가는시스템
queue.offer(new point(nr,nc,curr.dist+1,newcnt));
visit[nr][nc][newcnt]=true;
}
else {
queue.offer(new point(nr,nc,curr.dist+1,curr.cnt));
visit[nr][nc][curr.cnt]=true;
}
}
}
}
}
}
--코드--