Skip to content

05 최단 경로 #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

05 최단 경로 #28

wants to merge 9 commits into from

Conversation

kimyeheun
Copy link
Contributor

최단거리 문제 풀이 시 주의 사항

❗idea

  • 뭔가 어디를 가는 와중에 최소가 되는 시간을 찾거나 최소가 되는 무언가가 필요하다면! 최단거리 알고리즘을 떠올려보자!
  • 하지만, 다른 알고리즘도 고려해 봐야 한다.
  • 모든 노드 → 모든 노드 (경로 및 최단 거리) : 플로이드-워샬
  • 한 노드 → 모든 노드 (최단거리 + 가중치 양수) : 다익스트라

💡코드 작성 전에

  • 최단거리 알고리즘은 템플릿이 있는 것이 아님! 해당 알고리즘의 기본적인 형태에 매몰되지 말고 넓게 생각해볼 것!

지름길

  • 고찰
    • 이번주 알고리즘 분류를 보고 무조건 다익스트라로 풀어야 겠다고 생각하고 문제를 접근한 것이 화근이었습니다.

    • 처음에는 우선순위 큐에 <시작점, 끝점, 가중치>가 있는 노드를 넣고, 지름길로 얻을 수 있는 이득의 비율이 가장 큰 순서로 정렬하는 방식을 사용했습니다.

      PriorityQueue<Road> queue = new PriorityQueue<>((s, e) -> {
      	if (s.w == 0 || e.w == 0) return s.w - e.w;
      	int ss = (s.e - s.s) / s.w;
      	int ee = (e.e - e.s) / e.w;
      	
      	return ee - ss;
      });

      하지만, 이 문제는 단순히 가장 지름길을 먼저 선택한다고 해서 풀리는 문제가 아니라는 것을 깨달았습니다. (10%씩 줄어드는 지름길 두 개와 15% 줄어드는 지름길이 있다고 가정할 때, 10%씩 줄어드는 지름길 두 개를 선택하는 것이 훨씬 이득)

    • 이후 알고리즘에 집중하지 않고 문제를 찬찬히 읽어보았습니다.

      • 시작위치와 도착위치가 정해져 있다.
      • 한 좌표에서 출발하여 다음 좌표로 가는 경우가 어떤 경우인지 확실히 알 수 있다.
        • -1 위치에서 오는 경우, 지름길의 시작 위치에서 오는 경우
      • 범위가 10_000으로, int 배열을 만들 수 있는 크기이다.
    • 이와 같은 조건에서 dp로 풀 수 있겠다는 생각을 하게 되었고, 이대로 풀게 되었습니다.

  • 풀이 방식
    • 도착지점과 시작지점의 좌표를 set에 담았습니다.
    • 모든 지름길을 list에 저장하였습니다.
    • 이후, for문을 통해 10_000까지 순회하며 지름길이 있는 위치인지, 있다면 갱신하주는 방식으로 문제를 해결하였습니다.

숨바꼭질 3

  • 고찰
    • 이 문제는 visited 처리에서 문제를 많이 먹었었습니다.
    • +1 혹은 -1을 했을 때 갈 수 있는 시간이 *2를 통해 갈 수 있는 방식보다 무조건 적을 것이라고 생각하였고, *2를 통해 갈 수 있는 위치를 갱신 한 후 +1 로는 갈 수 없게 하였습니다.
    • 이렇게 한 결과, +1이나 -1로 갈 수 있는 시간이 더 적은 상황을 고려하지 못하게 되었고 ‘틀렸습니다.’가 나왔었습니다.
    • 그래서 visited 을 없애고 값을 비교했을 때 시간이 더 적게 나온 경우 갱신하는 방식을 사용하게 되었고, 문제를 풀 수 있었습니다.
    • 이 경우에는 최단거리를 구할 때, 한 번 방문한 곳은 다시 방문하지 않아도 된다는 그리디 사고방식이 문제가 된 것 같습니다.

서강그라운드

  • 풀이 방식
    • 문제를 읽고 다음 세 가지 조건을 뽑아내서 플로이드-워셜 알고리즘으로 해결하게 되었습니다.
      • 어떤 노드에서 낙하하는지 정해져 있지 않은 상황이다.
      • 수색범위가 정해져 있는 와중에 다른 지역까지의 최대 아이템을 습득해야하는 상황이다. (각 노드까지의 가중치를 알 수 있다.)
      • 모든 노드에서 모든 노드까지의 연결 여부를 알 수 있어야 한다.

택배

  • 의문
    • 이 문제 또한 모든 노드에서 다른 모든 노드와 연결 여부를 알아야 하므로 플로이드-워셜 알고리즘으로 풀 수 있을 것이라고 생각합니다.
    • 하지만, 어떤 방식으로 노드 간의 가중치와 경로를 저장하고 갱신해야 할지 직관적으로 와닿지 않아서 해결하지 못 했습니다.
  • 풀이 방식
    • 모든 노드에서 다른 노드까지의 다익스트라를 돌리며 본인 노드를 제외한 첫번째 노드를 계속 들고 가는 방식으로 문제를 해결하였습니다.

@kimyeheun kimyeheun changed the title 05 최단거리 05 최단 경로 Mar 1, 2025
Node now = queue.poll();
if (path[now.node] != 0) continue;
path[now.node] = now.route;
for(Node n : routes.getOrDefault(now.node, new ArrayList<>())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해시맵에 getOrDefault가 있는지 처음 알았네요!! 이 함수를 쓴 이유가 무엇인지 알 수 있을까욥

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants