Skip to content

Conversation

@Gyulguma
Copy link

@Gyulguma Gyulguma commented Apr 17, 2025

🚀 싸피 15반 알고리즘 스터디 13주차 [유병규]

📌 문제 풀이 개요

  • 이번 PR에서는 다음 5문제의 풀이를 포함합니다.
  • 각 문제에 대한 풀이 과정과 접근 방식을 설명합니다.

✅ 문제 해결 여부

  • 마법사 상어와 복제
  • 궁금한 민호
  • 놀이 공원
  • BFS 스페셜 저지
  • 청소년 상어

  • 시계 사진들
  • 달빛 여우
  • 주사위 윷놀이

💡 풀이 방법

문제 1: 마법사 상어와 복제

문제 난이도

  • 골드 1

문제 유형

  • 구현, 시뮬레이션

접근 방식 및 풀이

  • 물고기의 정보를 저장하는 자료구조와 물고기 냄새를 저장하는 자료구조, 물고기 마리 수를 저장하는 자료구조로 총 3개의 자료구조를 사용하여 문제를 해결하였습니다.
  • 물고기의 정보를 저장하는 자료구조를 처음에는 ArrayList로 구현하였지만 remove의 연산 시간이 너무 오래 걸려 시간 초과가 났습니다. 물고기의 정보를 Fish 객체로 저장하고 Fish 객체의 경우 중복되지 않기 때문에 remove 연산이 빠른 HashSet으로 자료구조를 변경하여 문제를 해결할 수 있었습니다.
  • 상어가 움직일 때 처음 시작 위치에 있는 물고기는 먹지 않는다는 것을 주의해야 합니다.

문제 2: 궁금한 민호

문제 난이도

  • 골드 2

문제 유형

  • 플로이드-워샬, 최단 경로

접근 방식 및 풀이

  • N개의 도시가 M개의 도로로 연결 되어 있을 때 A 도시에서 B 도시로 이동하는 데 걸리는 최소 시간을 정리한 정보가 주어진다. 이때 해당 정보를 만족하면서 도로의 개수가 최소일 때, 모든 도로의 시간의 합을 구하는 문제입니다.
  • 모든 도시가 각각의 도시와 주어진 정보 값을 가지는 도로로 연결되어 있다고 가정한 후, 각각의 도로가 주어진 정보를 만족하기 위해 필수로 존재해야하는 도로인지 판별하여 필수 도로만 계산하는 방법으로 접근하였습니다.
  • 필수 도로인지 판별하는 방법은 i에서 j로 가는 도로를 제거했을 때 i에서 j로가는 최단 거리를 구한 뒤 주어진 정보를 비교하는 방법을 사용했습니다. 경우는 다음과 같습니다.
    • 최단 거리 > 주어진 정보: 해당 도로는 필수로 있어야 하는 도로입니다.
    • 최단 거리 = 주어진 정보: 해당 도로는 없어도 되는 도로입니다.
    • 최단 거리 < 주어진 정보: 정보가 잘못되었습니다.

문제 3: 놀이 공원

문제 난이도

  • 골드 1

문제 유형

  • 이분 탐색

접근 방식 및 풀이

  • $N$명의 아이들이 $M$종류의 1인승 놀이기구를 타고 $1$번부터 $M$번까지 놀이기구의 운행 시간이 주어질 때 마지막 아이가 탑승하는 놀이기구의 번호를 구하는 문제입니다.
  • 전체 아이들이 놀이기구 탑승을 마친 최소 시간(분)을 찾기 위해 시간을 기준으로 이분 탐색을 진행하였습니다. 이분 탐색을 통해 최소 시간을 먼저 찾은 후 그 시간의 1분 전에 총 몇 명이 탈 수 있는지 계산하는 방법으로 접근하였습니다.
  • 최소 시간 1분 전에 총 탈 수 있는 인원 수를 구한 뒤 $N$에서 빼, 남은 아이들의 수를 구했습니다. 그리고 1분 전 상황에서 각 놀이기구를 타기 위해 대기해야 하는 시간을 구한 뒤 대기 시간이 가장 짧은 순(같다면 번호가 작은 순)으로 정렬하여 남은 아이들이 어느 놀이기구를 타게 될 지 구하여 문제를 해결하였습니다.

문제 4: BFS 스페셜 저지

문제 난이도

  • 골드 3

문제 유형

  • BFS

접근 방식 및 풀이

  • 이 문제는 $1 \sim N$까지 정점이 있고 정점 순회 정보가 주어질 때 올바른 BFS 순서인지 묻는 문제입니다. 문제는 1번 정점부터 시작하며 방문하지 않은 정점을 방문하는 순서는 중요하지 않다는 특징을 가지고 있습니다.
  • 먼저 간선 정보를 저장한 후, 1번 정점을 시작으로 BFS를 수행할 때 나올 수 있는 순서 집합을 생성하였습니다. 순서 집합이란 BFS를 수행했을 때 해당 깊이에서 나올 수 있는 정점들의 집합입니다. 예를 들어, 순서 집합이 [[1], [2, 3], [4], [], []]와 같다면 이는 첫 번째 나올 수 있는 정점은 1, 두 번째는 23, 세 번째는 4라는 의미입니다. 이 순서 집합을 생성한 뒤 입력 값의 순서가 위 순서 집합에 해당하는 지 판단하여 문제를 해결하였습니다.

문제 5: 청소년 상어

문제 난이도

  • 골드 1

문제 유형

  • 구현, 시뮬레이션, 백트래킹

접근 방식 및 풀이

  • 문제의 요구 사항은 다음과 같습니다.
    • 물고기: 한 칸에 물고기가 한 마리 존재, 1~16 사이의 번호와 방향(상하좌우 대각선)을 가짐
    • 이동
      • 한 칸 이동 가능
      • 빈 칸, 다른 물고기가 있는 칸만 이동 가능(물고기가 있을 경우 서로 위치 교환)
      • 상어가 있거나 공간의 경계를 넘는 칸 이동 불가
      • 이동 불가 시 이동할 수 있을 때까지 방향을 45도 반시계 회전
    • 상어: (0,0)에서 시작하며, 물고기를 먹으면 물고기의 방향을 가짐
    • 이동
      • 방향에 있는 칸으로 이동 가능하며 한 번에 여러 개의 칸 이동 가능
      • 도착한 칸의 물고기를 먹음
      • 이동하는 중에 지나가는 칸에 있는 물고기는 먹지 않음
      • 이동할 수 있는 칸이 없으면 공간에서 벗어나 집으로 복귀
  • 물고기 이동의 경우 요구 사항을 그대로 구현하였으며 상어 이동의 경우 경우의 수가 최대 3개가 나올 수 있으므로 백트래킹을 사용해 문제를 해결하였습니다.
  • 백트래킹 중 상태 복원 시 물고기의 상태를 저장하는 map 자료 구조의 상태 복원이 올바르게 구현되지 않아 시간이 걸렸던 문제였습니다. (깊은 복사는 구현했지만 복원 시기를 잘못 선택하여 오류가 생겼었습니다.)

문제 6: 시계 사진들

문제 난이도

  • 플레티넘 4

문제 유형

  • 문자열, KMP

접근 방식 및 풀이

  • 길이가 동일한 $N$개의 시계 바늘을 가진 시계가 있습니다. 시계 바늘들이 각각 특정 각도로 놓여있을 때 찍은 사진이 두 개가 있습니다. 각 사진의 시계 바늘들이 놓여있는 각도 $a_i$가 주어질 때, 사진을 돌려 두 사진의 시계가 같은 시각을 나타낼 수 있는 지 판단하는 문제입니다.
  • 그림과 같이 주어진 정보로 시계를 그렸을 때 회전하여 동일한 그림이 나오는 지 판단하는 문제이기 때문에 각 바늘의 사잇각을 저장하는 배열을 구해 두 배열이 같은 값을 가질 수 있는 지로 접근하였습니다. 사잇각을 구할 때 모든 바늘 간의 사잇각을 구해야 하기에 첫바늘과 마지막 바늘간의 사잇각도 구해야 합니다.

image

  • 두 배열을 비교할 때 시작점을 0 based-indexing 기준으로 0~n-1까지 가질 수 있기 때문에 비교할 배열(2번 배열) 뒤에 동일한 배열(2번 배열)을 붙여 크기가 2n인 새로운 배열을 만든 뒤 해당 배열이 1번 배열을 포함하는 지를 kmp를 사용하여 문제를 해결하였습니다.

Comment on lines +119 to +147
Copy link
Contributor

Choose a reason for hiding this comment

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

상어가 이동하는 경로를 DFS로 구현한 게 좋아보이네요,, 저는 삼중 반복문으로 짰는데 DFS 코드가 더 깔끔해보여요

Copy link
Author

Choose a reason for hiding this comment

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

삼중 반복문으로도 해결할 수 있군요. 저는 dfs만 떠올라서 위와 같이 구현하였는데, 여러 해결 방법을 아는 것도 중요하다 생각해서 삼중 반복문도 참고해보겠습니다!

Comment on lines +59 to +73
Copy link
Contributor

Choose a reason for hiding this comment

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

complete graph를 미리 만들어놓고 간선을 하나씩 제거하는 방법도 있었군요?

Copy link
Author

Choose a reason for hiding this comment

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

저도 참고해서 해결한 문제인데, 모든 간선을 하나씩 제거했을 때 이 간선이 최단 거리를 위해서 반드시 필요한 간선인 지 확인하는 방법이 참신하다고 생각했습니다. 여러 간선을 조합과 같이 선택해서 확인하는 것이 아니라 각각의 간선을 확인해서 필요한 간선이면 제거하지 않고 다음 다리를 판단하는 것이 인상적인 풀이 방법이었습니다.

Comment on lines +63 to +78
Copy link
Contributor

Choose a reason for hiding this comment

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

이 부분을 PQ 없이 구현하면 조금 더 효율적인 코드가 될 것 같습니다!

Copy link
Author

Choose a reason for hiding this comment

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

확실히 단순 정렬이라 PQ를 사용하지 않고 구현하는 것이 더 효율적인 것 같습니다! 당시에 드디어 풀었다는 기쁨에 당장 생각나는 방법으로 구현했었는데, 좀 더 차분히 문제를 푸는 연습이 필요한 것 같습니다. 리뷰 감사합니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants