알고리즘/백준
14503_ 해결 못 함
베리영young
2024. 1. 9. 14:46
구현 문제로 조건이 까다롭다
1. while문을 활용했고
2. 재귀문을 활용했다
1. while 사용
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int[] dx = {1,0,-1,0};
static int[] dy = {0,1,0,-1};
static int n,m, rx,ry, direction;
static int[][] map, robot;
static int answer = 0;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
rx = Integer.parseInt(st.nextToken());
ry = Integer.parseInt(st.nextToken());
direction = Integer.parseInt(st.nextToken());
map = new int[n][m];
robot = new int[n][m];
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < m; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
robot[rx][ry] = 1; //로봇 위치 표시
int hwak = 0;
while (n*m>=hwak++) {
System.out.println(hwak++);
//현재 칸 청소
cleanTheRoom(rx,ry);
if(isAllClean(rx,ry)) { //청소 여부 판단 -> 빈칸없는경우
//후진 확인
//종료 - 후진x
if(!canGoBack(rx,ry,direction)) break;
//후진 후, 1번(현재 자리 청소)
else{
goBack(rx,ry,direction);
cleanTheRoom(rx,ry);
//isAllClean 다시 하기
}
}
else { //청소 여부 판단 -> 빈칸있는경우
rotate90(direction);
goFront(rx,ry); //앞이 비었따면 + 청소
}
}
System.out.println(answer);
}
private static void goFront(int rx, int ry) {
robot[rx][ry] = 0;
rx += dx[direction];
ry += dy[direction];
robot[rx][ry] = 1;
cleanTheRoom(rx,ry);
}
private static void rotate90(int direction) {
if(direction==0) direction=3;
else if(direction==1) direction=0;
else if (direction==2) direction=1;
else direction=2;
}
private static void goBack(int rx, int ry, int direction) {
robot[rx][ry] = 0;
int move = (direction+2)%4;
robot[rx+move][ry+move] = 1; //움직이기
}
private static boolean isAllClean(int rx, int ry) {
for (int d = 0; d < 4; d++) {
int x = rx + dx[d];
int y = ry + dy[d];
if(x>=0&&x<n &&y>=0&&y<m && map[x][y]==0) return false; //치우러 가기
}
return true; //후진하기
}
private static void cleanTheRoom(int rx, int ry) {
if(map[rx][ry] == 0) {
map[rx][ry] = 2; //청소 완료!!!!!!!!!!!!!!!!!!!!!!!!
answer++;
}
}
private static boolean canGoBack(int rx, int ry, int direction) {
int x = rx + dx[(direction+2)%4];
int y = ry + dy[(direction+2)%4];
if(x<0||x>=n||y<0||y>=m || map[x][y]==1 || map[x][y]==2) return false;
return true;
}
}
-> 무한 루프를 돌고 있음.
-> 4방이 모두 막힌 경우가 아닌 경우에 뭔가 처리를 해야 하는 거 같은데... 뭘까..
-> 4방 탐색 후 1과 2가 섞여있을 때가 문제인 거 같다. 뒤로 갔다 앞으로 갔다 하는 거 같음
-> 메소드를 너무 자잘하게 나누어 놓은 거 같기도 하다.
2. 재귀
import java.io.*;
import java.util.*;
public class Main {
static int[] dx = {1,0,-1,0};
static int[] dy = {0,1,0,-1};
static int n,m, rx,ry, dir;
static int[][] map; //로봇이 있떤 곳은 어차피 2
static int answer = 0;
public static void main(String[] args) throws IOException {
inputData();
operateRobot(rx, ry, dir);
System.out.println(answer);
}
private static void operateRobot(int x, int y, int dir) {
//-1:로봇 0:빈칸 1:벽 2:청소된 곳
map[x][y] = -1; //로봇의 현재 위치:-1
//4방 탐색
for(int d=0; d<4; d++) {
dir = (dir + 3) % 4; //반시계로 돌기!!!!
int nx = x + dx[dir];
int ny = y + dy[dir];
if(nx>=0&&nx<n&&ny>=0&&ny<m && map[nx][ny]==0) {
answer++;
map[x][y] = 2;
map[nx][ny] = -1;
operateRobot(nx, ny, dir);
return; //없으면 무한 돌아감
}
dir = (dir+2) %4;
int bx = x+dx[dir];
int by = y+dy[dir];
if(bx>=0&&bx<n&&by>=0&&by<m && map[bx][by]!=1) {
map[x][y] = 2;
map[bx][by] = -1;
operateRobot(bx, by, dir);
}
}
}
private static void inputData() {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
rx = sc.nextInt();
ry = sc.nextInt();
dir = sc.nextInt();
map = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
map[i][j] = sc.nextInt();
}
}
} //초기 데이터 입력 받기
}
.
=> stackOverFlow가 남. 여기도 무한 재귀를 돌고 있나?
=> 에러 확인을 할 수 없는 상황이라서 답답..
=> while보다 깔끔하게 코드가 떨어져서, 코드를 수정한다면 2번 코드를 수정하는 게 좋아 보인다.. 4방 탐색이 불가능한 경우에 처리가 더 용이해 보임