알고리즘 & 자료구조/문제 풀이
[프로그래머스 알고리즘 고득점 Kit][그래프][Java] 방의 개수
수수다
2026. 4. 18. 00:15
https://school.programmers.co.kr/learn/courses/30/lessons/49190
프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
내가 지나간 점을 내가 지나 온 길이 아닌 방향으로 도달한다면 하나의 방이 생김
그렇다면 내가 밟은 점을 기록하고 다시 도달했을 때
밟은 점인지 지나온 길인지 아닌지 판별해야함
x * row + y 와 같은 인코딩 방식 + Set 으로 진행하려다가
class로 풀어보고 싶었음
같은 x값 y값이라도 객체가 다르면 다르다고 인식하기 때문에
equals 와 hashCode를 오버라이드 해줘서 같은 좌표면 같은 점이라 인식하도록 함
문제를 풀 수 있었음
여기서 교점이 꼭 점이 아닐 수 있다는 부분이
생각하기 어려웠음
그래서 하나의 움직임을 2만큼 움직인다고 하고 2개로 쪼개서 모든 점을 두번씩 저장하게 했음
그래서 중간 대각선의 교점도 같은 Point class로 처리할 수 있게 되었음
import java.util.*;
class Solution {
static class Point {
final int x;
final int y;
Point(int x, int y){
this.x = x;
this.y = y;
}
//좌표를 인코딩해도되지만 클래스로 한 번 풀어보고 싶었음.
//new 로 생성하면 같은 좌표여도 다른 객체로 인식함 그래서 아래의 메서드들을 오버라이드해줬음
@Override
public boolean equals(Object o) {
if(this == o) return true; //비교대상이 같은 주소인가(같은 객체인가)
if(!(o instanceof Point)) return false; //Point class의 객체인가
Point point = (Point) o; //Point인 것만 내려오니까 형변환 안전.
return x == point.x && y == point.y; //내용물 비교
}
//해시 기반 컬렉션(HashSet, HashMap)은 먼저 hashCode()보고 어느 칸(bucket)에 넣을지 정하고
//같은 위치에 후보가 있으면 그때 equals()로 진짜 같은지 비교.
@Override
public int hashCode() {
return Objects.hash(x, y);
}
//equals() 가 true 라면 hashCode()는 같아야함
//hashCode()가 같다고 해서 equals가 true일 필요는 없음
//해시 충돌로 인해 다른 객체여도 같은 값을 가지고 있을 수 있어서
}
static class Edge {
final Point from;
final Point to;
Edge(Point from, Point to) {
this.from = from;
this.to = to;
}
@Override
public boolean equals(Object o) {
if(this == o) return true;
if(!(o instanceof Edge)) return false;
Edge edge = (Edge) o;
return Objects.equals(from, edge.from) && Objects.equals(to, edge.to);
}
@Override
public int hashCode() {
return Objects.hash(from, to);
}
}
final int[] dx = {0, 1, 1, 1, 0, -1, -1, -1};
final int[] dy = {1, 1, 0, -1, -1, -1, 0, 1};
public int solution(int[] arrows) {
Set<Point> visitedPoints = new HashSet<>();
Set<Edge> visitedEdges = new HashSet<>();
Point curr = new Point(0, 0);
visitedPoints.add(curr);
int answer = 0;
for(int arrow : arrows) {
//대각선 교차를 처리하기 위해서 한번의 움직임을 2번 나눠서 저장함
for(int i=0; i<2; i++) {
Point next = new Point(curr.x + dx[arrow], curr.y + dy[arrow]);
Edge edge = new Edge(curr, next);
Edge reverseEdge = new Edge(next, curr);
if(visitedPoints.contains(next) && !visitedEdges.contains(edge)){
answer++;
}
visitedPoints.add(next);
visitedEdges.add(edge);
visitedEdges.add(reverseEdge);
curr = next;
}
}
return answer;
}
}