총 10분 중 11분
2001
시즌 2개, 그리고 영화
시즌 2:
5화
“아일랜드”
출연: 이나영, 김민준, 김민정, 현빈
장르: 애초에 역경을 딛고 이룩하는 숭고한 사랑이란 없다. 그 역경 자체가 사랑이다.
프로그램 특징: 그 곳에서 살아남는 사랑이 어떤 모습으로 걸어오는지 기다려 보고 싶다.
장르: 애초에 역경을 딛고 이룩하는 숭고한 사랑이란 없다. 그 역경 자체가 사랑이다.
프로그램 특징: 그 곳에서 살아남는 사랑이 어떤 모습으로 걸어오는지 기다려 보고 싶다.
회차
Algorithm/Greedy
[Java][BOJ 19941] 햄버거 분배
728x90
반응형
문제 링크
문제 파악
식탁의 길이 N, 햄버거를 선택할 수 있는 거리 K, 사람과 햄버거의 위치가 주어졌을 때 햄버거를 먹을 수 있는 사람의 최대 수를 구하는 프로그램을 작성하시오. 첫 줄에 N과 K가 주어지고 다음 줄에 사람과 햄버거의 위치가 문자 P(사람)과 H(햄버거)로 주어진다.
- 1 <= N <= 20000
- 1 <= K <= 10
20 1
HHPHPPHHPPHPPPHPHPHP //8
20 2
HHHHHPPPPPHPHPHPHHHP //7
접근 방법
햄버거 | 사람 | 햄버거 | 사람 | 햄버거 | 사람 | 햄버거 | 햄버거 | 사람 | 사람 | 햄버거 | 사람 |
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
K = 2인 경우에는 6명 모두가 햄버거를 먹을 수 있다.
- 2번 위치에 있는 사람: 1번 위치에 있는 햄버거
- 4번 위치에 있는 사람: 3번 위치에 있는 햄버거
- 6번 위치에 있는 사람: 5번 위치에 있는 햄버거
- 9번 위치에 있는 사람: 7번 위치에 있는 햄버거
- 10번 위치에 있는 사람: 8번 위치에 있는 햄버거
- 12번 위치에 있는 사람: 11번 위치에 있는 햄버거
처음에 그리디로 생각했는데 9번의 경우 가장 가까운 값으로 먹으면 10번이 11번 햄버거를 먹어서 12번이 아무것도 못먹게 된다.
그래서 백트래킹인건가? dfs로 각 P마다 1-K번 모두 점프 시도해보았다. (근데 가장 가까운 값을 먹는게 아니라 가장 작은 인덱스 값부터 먹는 그리디였으면 가능했다. )
- 처음에는 한 칸 점프, 만약 K가 1보다 크면, 2칸 점프해서 dfs... K칸까지 점프하는 dfs 실행 후 Math.max로 출력
- String 에서 P를 찾아 이동 가능한 거리를 for문으로 돌면서 먹을 수 있는 지 확인한다.
- 먹을 수 있으면 햄버거 eaten 표시와
사람별로 먹었는지를 나타내는 pEaten를 True 표시한다. - 먹을 수 없거나 H면 idx+1해서 다음 dfs 실행한다.
- 인덱스가 String 길이가 되면 종료
static char[] line;
static boolean[] eaten;
static boolean[] pEaten;
dfs(0,0);
dfs(int idx, int cnt) {
if (idx >= N) {
maxCnt = Math.max(maxCnt, cnt);
return;
}
if (line[idx] == 'P') {
boolean matched = false;
for (int jump = -K; jump <= K; jump++) {
int target = idx + jump;
if (target < 0 || target > N-1) continue;
if (line[target] == 'H' && !eaten[target]) {
// 먹기
eaten[target] = true;
dfs(idx + 1, cnt + 1);
eaten[target] = false;
matched = true;
}
}
if (!matched) dfs(idx + 1, cnt); // 못 먹고 넘어감
} else {
dfs(idx + 1, cnt); // 사람이 아닌 경우 그냥 넘어감
}
}
는 시간초과가 난다. 백트래킹이고. 그리디도 시간복잡도는 O(20000*20)로 똑같을 것 같은데 아니었다.
코드 구현
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int K = sc.nextInt();
String line = sc.next();
char[] arr = line.toCharArray();
boolean[] eaten = new boolean[N];
int count = 0;
for (int i = 0; i < N; i++) {
if (arr[i] == 'P') {
// 앞뒤로 k칸 범위 탐색
for (int j = i - K; j <= i + K; j++) {
if (j < 0 || j >= N) continue;
if (arr[j] == 'H' && !eaten[j]) {
eaten[j] = true;
count++;
break; // 한 사람은 햄버거 하나만 먹음
}
}
}
}
System.out.println(count);
}
}
배우게 된 점
백트래킹은 시간복잡도가 더 작을 줄 알았는데.. 아니었다. 20개의 문자에 대해 K개의 선택을 하니까 20^K로 계산해야 한다.
질문
728x90
'Algorithm > Greedy' 카테고리의 다른 글
[JAVA][BOJ 1911] 흙길 보수하기 - 그리디 pq (1) | 2025.04.24 |
---|
2025:06:26
Algorithm/Greedy
[Java][BOJ 19941] 햄버거 분배