프로그래머스
2021 카카오 채용연계형 인턴십
[level 2] 거리두기 확인하기 - 81302
https://school.programmers.co.kr/learn/courses/30/lessons/81302#
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
내가 처음 생각해본 풀이 방식은 dfs를 이용하여
오른쪽과 아래쪽만 체크하면서 모든 배열을 순회하면 된다고 생각했다
그래서 아래와 같이 코드를 짰다.
[실패한 코드]
public boolean check(String[] room, int y,int x,int cnt){
if(cnt==3) return true;
else if(x>=5 || y>=5) return true;
else if(room[y].charAt(x)=='X') return true;
if(room[y].charAt(x)=='P') return false;
else{
if(!check(room, y+1, x, cnt+1)){
return false;
}else if(!check(room, y, x+1, cnt+1)){
return false;
}
}
return true;
}
그러나 이런 방식은
O P
P X
와 같은 형태를 검사하지 못한다.
따라서 4방향을 모두 검사해보고 방문한곳을 따로 체크해두면서
확인하는 방식으로 바꿨다.
[통과한 코드]
import java.util.Arrays;
public class 카카오2021인턴십_거리두기확인하기_방법1 {
public static void main(String[] args) {
Solution sol = new Solution();
String[][] places = new String[][]{{"POOOP", "OXXOX", "OPXPX", "OOXOX", "POXXP"}, {"POOPX", "OXPXP", "PXXXO", "OXXXO", "OOOPP"}, {"PXOPX", "OXOXP", "OXPOX", "OXXOP", "PXPOX"}, {"OOOXX", "XOOOX", "OOOXX", "OXOOX", "OOOOO"}, {"PXPXP", "XPXPX", "PXPXP", "XPXPX", "PXPXP"}};
System.out.println(Arrays.toString(sol.solution(places)));
}
static class Solution {
public int[] solution(String[][] places) {
int[] answer = new int[]{1, 1, 1, 1, 1};
int[] dx = new int[]{1, 0, -1, 0};
int[] dy = new int[]{0, 1, 0, -1};
for (int t = 0; t < 5; t++) {
String[] room = places[t];
boolean[][] visited = new boolean[5][5];
//세로
for (int y = 0; y < 5; y++) {
// 가로
for (int x = 0; x < 5; x++) {
if (room[y].charAt(x) == 'P') {
if (answer[t] == 0) break;
visited[y][x] = true;
for (int i = 0; i < 4; i++) {
int ny = y + dy[i];
int nx = x + dx[i];
if (!check(room, ny, nx, 1, visited)) {
answer[t] = 0;
break;
}
}
}
if (answer[t] == 0) break;
}
if (answer[t] == 0) break;
}
}
return answer;
}
public static boolean check(String[] room, int y, int x, int cnt, boolean[][] visited) {
int[] dx = new int[]{1, 0, -1, 0};
int[] dy = new int[]{0, 1, 0, -1};
if (cnt == 3) return true;
else if (y < 0 || x < 0 || x >= 5 || y >= 5) return true;
else if (room[y].charAt(x) == 'X') return true;
visited[y][x] = true;
if (room[y].charAt(x) == 'P') return false;
else {
for (int i = 0; i < 4; i++) {
int ny = y + dy[i];
int nx = x + dx[i];
if (ny < 0 || nx < 0 || nx >= 5 || ny >= 5) continue;
if (visited[ny][nx]) continue;
visited[ny][nx] = true;
if (!check(room, ny, nx, cnt + 1, visited)) return false;
visited[ny][nx] = false;
}
}
return true;
}
}
}
이 방법 이외에 더 좋은 방법이 있을까 생각해봤는데
아래와 같은 방식도 있을 것 같다.
1. 모든 사람들의 좌표를 구한다.
2. 사람들간의 거리를 구한다
3. 거리가 1인경우 무조건 거리두기를 어긴다.
4. 거리가 2인경우
4-1. 두 사람이 같은 행/열에 있는 경우
P 또는 PXP
X
P
위와 같이 두사람 사이에 파티션이 있어야 거리두기를 지킨다.
4-2. 두 사람이 다른 행/열에 있는 경우
PX
XP
위와 같이 두개의 파티션이 있어야 거리두기를 지킨다.
이러한 방식으로 코딩을 진행해보면
public class 카카오2021인턴십_거리두기확인하기_방법1 {
public static void main(String[] args) {
Solution sol = new Solution();
String[][] places = new String[][]{{"POOOP", "OXXOX", "OPXPX", "OOXOX", "POXXP"}, {"POOPX", "OXPXP", "PXXXO", "OXXXO", "OOOPP"}, {"PXOPX", "OXOXP", "OXPOX", "OXXOP", "PXPOX"}, {"OOOXX", "XOOOX", "OOOXX", "OXOOX", "OOOOO"}, {"PXPXP", "XPXPX", "PXPXP", "XPXPX", "PXPXP"}};
System.out.println(Arrays.toString(sol.solution(places)));
}
static class Solution {
public int[] solution(String[][] places) {
int[] answer = new int[]{1, 1, 1, 1, 1};
for (int t = 0; t < 5; t++) {
String[] rooms = places[t];
List<Coordinate> coordinates = new ArrayList<>();
for (int i = 0; i < 5; i++) {
String room = rooms[i];
for (int j = 0; j < 5; j++) {
if (room.charAt(j) == 'P') {
coordinates.add(new Coordinate(i, j));
}
}
}
for (int i = 0; i < coordinates.size(); i++) {
int y = coordinates.get(i).y;
int x = coordinates.get(i).x;
for (int j = i + 1; j < coordinates.size(); j++) {
int ny = coordinates.get(j).y;
int nx = coordinates.get(j).x;
if (!check(rooms, y, ny, x, nx)) {
answer[t] = 0;
}
}
}
}
return answer;
}
}
static class Coordinate {
public int y;
public int x;
public Coordinate(int y, int x) {
this.y = y;
this.x = x;
}
}
static public boolean check(String[] rooms, int y, int ny, int x, int nx) {
int manhattan = Math.abs(y - ny) + Math.abs(x - nx);
if (manhattan <= 1) {
return false;
} else if (manhattan == 2) {
if (y == ny) {
if (rooms[y].charAt(Math.min(x, nx) + 1) == 'X') {
return true;
} else {
return false;
}
} else if (x == nx) {
if (rooms[Math.min(y, ny) + 1].charAt(x) == 'X') {
return true;
} else {
return false;
}
} else {
if (x < nx) {
if (rooms[y].charAt(x + 1) == 'X' && rooms[ny].charAt(nx - 1) == 'X') {
return true;
} else {
return false;
}
} else {
if (rooms[y].charAt(x - 1) == 'X' && rooms[ny].charAt(nx + 1) == 'X') {
return true;
} else {
return false;
}
}
}
} else return true;
}
}
위와 같이 해결할 수 있다.
'공부 일지 > 스터디 자료' 카테고리의 다른 글
[스터디] 기술스터디 2주차 (0) | 2023.04.16 |
---|---|
기술스터디 1주차 (0) | 2023.04.08 |
11회차 스터디 준비 (0) | 2022.09.16 |
10주차 스터디 준비 (0) | 2022.09.08 |
9회차 스터디 (0) | 2022.08.30 |