| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
Tags
- 토마토
- 깃허브 프로필
- 정렬
- 깃허브
- 1932
- Java
- DP
- 조합
- 15686
- 정수 삼각형
- 분할정복
- dfs
- Summer/Winter Coding(~2018)
- BFS
- 알고리즘
- 프로그래머스
- 구현
- 완전탐색
- 알고리즘고득점Kit
- GIT
- Python
- 그래프탐색
- 월간 코드 챌린지 시즌1
- 이코테
- 그래프
- 다익스트라
- 백준
- 프로그래멋
- Lv2
- 자바
Archives
- Today
- Total
갱스터하우스
[Java] 백준 14938.서강그라운드 본문
➡️문제 링크
https://www.acmicpc.net/problem/14938
💡아이디어
BFS
처음에는 각 정점마다의 가중치가 달라 다익스트라로 접근해야겠다고 생각했는데,
구현하는 과정에서 무엇을 미리 저장하는 건지 헷갈려서 일단 BFS로 풀었다
✏️문제 풀이
1. BFS - 성공
출발지점을 1부터 N까지 돌며 수색범위 내에서 탐색을 진행한다
그리고 그 값들 중 가장 큰 값을 갱신하다.
그런데 이 풀이는 정말 운 좋게 맞은거다. 각 정점간의 거리마다 가중치가 다르므로 항상 최단거리를 보장해주지 못하는 로직이다.
import java.io.*;
import java.util.*;
public class Main {
static int N, M;
static int [] item;
static List<List<int []>> graph = new ArrayList<>();
static boolean [] visited;
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken()); // 지역 수
M = Integer.parseInt(st.nextToken()); // 수색범위
int R = Integer.parseInt(st.nextToken()); // 길의 개수
item = new int[N+1];
st = new StringTokenizer(br.readLine());
for(int i = 1; i <= N; i++) {
item[i] = Integer.parseInt(st.nextToken()); // 각 구역별 아이템 수
}
for(int i = 0; i <= N; i++) graph.add(new ArrayList<>());
for(int r = 0; r < R; r++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken()); // 지역 번호 a
int b = Integer.parseInt(st.nextToken()); // 지역 번호 b
int c = Integer.parseInt(st.nextToken()); // 길이의 길이
graph.get(a).add(new int [] {b, c});
graph.get(b).add(new int [] {a, c});
}
// 구현
int result = 0;
for(int i = 1; i <= N; i++) {
result = Math.max(result, bfs(i)); // 낙하 지점
}
// 정답
System.out.println(result);
}
static int bfs(int start) {
visited = new boolean[N+1];
visited[start] = true; // 출발지점 방문
Queue<int []> que = new LinkedList<>();
que.add(new int[] {start, 0}); // 정점, 도달 거리값
while(!que.isEmpty()) {
int [] point = que.poll();
if(point[1] >= M) continue; // 이미 수색범위 넘어감.
for(int i = 0; i < graph.get(point[0]).size(); i++) {
int [] arr = graph.get(point[0]).get(i); // 정점 거리
if(point[1] + arr[1] > M) continue; // 넘어감
visited[arr[0]] = true;
que.add(new int [] {arr[0], point[1] + arr[1]});
}
}
int count = 0;
for(int i = 1; i <= N; i++) {
if(visited[i]) count += item[i];
}
return count;
}
}
2. 다익스트라 - 성공
각 정점을 출발 정점으로 두어, 모든 정점간의 "최소 거리"를 다익스트라를 이용해 구하고(왜냐하면 간선마다 가중치가 다르니까!)
마지막에 각 거리가 수색범위 이하인지 판단하며 최대 아이템을 갱신해나간다.
이렇게 보니 다익스트라를 어떻게 활용하는지 알게 됐다.
나는 처음부터 다익스트라를 돌리면서 바로 수색범위 m을 탐색하려고 했는데 그게 아니었
import java.io.*;
import java.util.*;
public class Main {
static int N, M;
static int [] item;
static List<List<int []>> graph = new ArrayList<>();
static int [] dist;
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken()); // 지역 수
M = Integer.parseInt(st.nextToken()); // 수색범위
int R = Integer.parseInt(st.nextToken()); // 길의 개수
item = new int[N+1];
st = new StringTokenizer(br.readLine());
for(int i = 1; i <= N; i++) {
item[i] = Integer.parseInt(st.nextToken()); // 각 구역별 아이템 수
}
for(int i = 0; i <= N; i++) graph.add(new ArrayList<>());
for(int r = 0; r < R; r++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken()); // 지역 번호 a
int b = Integer.parseInt(st.nextToken()); // 지역 번호 b
int c = Integer.parseInt(st.nextToken()); // 길이의 길이
graph.get(a).add(new int [] {b, c});
graph.get(b).add(new int [] {a, c});
}
// 구현
int result = 0;
for(int i = 1; i <= N; i++) {
result = Math.max(result, dijkstra(i)); // 낙하 지점
}
// 정답
System.out.println(result);
}
static int dijkstra(int start) {
dist = new int[N+1];
Arrays.fill(dist, Integer.MAX_VALUE);
dist[start] = 0; // 출발지점 초기화
// 짧은 거리 순으로 pq 정렬
PriorityQueue<int []> pq = new PriorityQueue<>((a, b) -> a[1] - b[1]);
pq.add(new int[] {start, 0}); // 정점, 도달 거리값
while(!pq.isEmpty()) {
int [] point = pq.poll();
int curNum = point[0]; // 현재 정점
int curDist = point[1]; // 현재 거리
if(dist[curNum] < curDist) continue; // 현재 경로보다 더 짧은 경로 존재 -> 넘어가기
for(int i = 0; i < graph.get(curNum).size(); i++) {
int [] next = graph.get(curNum).get(i); // 정점 거리
int nextDist = dist[curNum] + next[1]; // 다음 값
if(dist[next[0]] > nextDist) { // 새로운 정점의 거리가 더 작은경우
dist[next[0]] = nextDist;
pq.add(new int[] {next[0], nextDist});
}
}
}
// 수색 범위 M 이내
int count = 0;
for(int i = 1; i <= N; i++) {
if(dist[i] <= M) count += item[i];
}
return count;
}
}
가중치가 양수 + 간선마다 가중치 다름
-> 다익스트라 잊지 말자!
'코테 문제 > 백준' 카테고리의 다른 글
| [Java] 백준 14503.로봇 청소기 (0) | 2026.03.27 |
|---|---|
| [Java] 백준 14502.연구소 (0) | 2026.03.27 |
| [Java] 백준 1753.최단 경로 (0) | 2026.03.17 |
| [Java] 백준 15686.치킨 배달 (0) | 2026.03.13 |
| [Java] 백준 13549.숨바꼭질 3 (0) | 2026.03.12 |