일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 포트앤어댑터 아키텍처
- 파이썬
- springboot
- UML
- 세그먼트 트리
- pandas
- 헥사고날 아키텍처
- 이펙티브 자바
- 위상정렬
- 백준
- 알고리즘
- 다익스트라
- dfs
- 비트마스크
- dataframe
- BFS
- ddd
- docker
- series
- 문자열
- JPA
- 자바
- 데이터 flow
- spring security
- disjoint set
- equals
- DP
- java
- Redis
- 스프링
- Today
- Total
코딩못하는사람
22115 창영이와 커피 [DP] 본문
https://www.acmicpc.net/problem/22115
22115번: 창영이와 커피
커피는 종류별로 하나씩 준비되어 있기 때문에, 동일한 커피를 여러 개 마실 수 없음에 유의하라.
www.acmicpc.net
1.접근
백트래킹으로 생각하고 풀었다가 시간초과를 맞았다. k가 커질 수록 시간이 급격히 늘어나는 코드였다.
얻어야하는 카페인양과 커피들의 카페인양을 보고 냅색문제처럼 최적 부분 구조로 나누어 풀 수 있다는걸 알았다.
2.풀이
각 커피에 카페인이 1, 2, 3, 4, 5 가 들어있고 마셔야하는 카페인이 15라고 가정해보자.
만약 5가 커피의 최소 개수를 위해 꼭 마셔야하는 커피라면 15에서 5를 뺀 10의 카페인을 1,2,3,4커피를 가지고 마시는 경우 +1이 최소 개수의 커피를 마시는 케이스일 것이다. 즉 다이나믹 프로그래밍의 최적부분구조를 만족한다.
따라서 2차원 배열을 생성해서 DP[카페인][커피]를 생성한다.
커피를 마시는 순서는 상관없이 Bottom UP 방식으로 쌓아간다.
현재 인덱스의 커피값을 뺀 부분 +1과 안마신다는 가정으로 옆에서 가져오는 값을 비교한다.
DP[카페인][커피인덱스]=min(DP[카페인-커피인덱스의 카페인값][커피인덱스-1]+1, DP[카페인][커피인덱스-1])
그 후 기저 사례를 체크해주면 된다.
3.코드
import java.io.BufferedReader; | |
import java.io.IOException; | |
import java.io.InputStreamReader; | |
import java.util.Arrays; | |
import java.util.Collections; | |
public class 창영이와커피_22115 { | |
static int n,k,ans; | |
static int[][] arr; | |
static int cant=1001; | |
public static void main(String[] args) throws IOException { | |
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | |
String[] s = br.readLine().split(" "); | |
n=Integer.parseInt(s[0]); | |
k=Integer.parseInt(s[1]); | |
String[] ss=br.readLine().split(" "); | |
int [] coffee=new int[ss.length]; | |
for (int i = 0; i < ss.length; i++) { | |
coffee[i]=Integer.parseInt(ss[i]); | |
} | |
arr=new int[k+1][n+1]; | |
for (int i = 0; i < n+1; i++) { | |
arr[0][i]=0; | |
} | |
for (int i = 1; i <k+1; i++) { | |
for (int j = 0; j <n+1; j++) { | |
arr[i][j]=cant; | |
} | |
} | |
for (int i = 1; i <k+1; i++) { | |
for (int j = 1; j <n+1; j++) { | |
if (i-coffee[j-1]<0) arr[i][j]=arr[i][j-1]; | |
else if (!(arr[i - coffee[j-1]][j - 1] == cant && arr[i][j - 1] == cant)) { | |
arr[i][j]=Math.min(arr[i][j-1],arr[i-coffee[j-1]][j-1]+1); | |
} | |
} | |
} | |
ans=arr[k][n]; | |
if (ans == cant) { | |
System.out.println(-1); | |
} else { | |
System.out.println(ans); | |
} | |
} | |
} |
4.배운점
오랜만에 만나보는 문제라 다이나믹 프로그래밍적 사고를 하는데 오래걸렸다.
정렬도 생각났지만 순서가 상관없이 쌓아 올라간다는게 중요했다.
DP 에서 기저 사례를 더 꼼꼼히 체크하자.
'백준 문제풀이(JAVA,Python)' 카테고리의 다른 글
1800 인터넷 설치( 다익스트라 ,이분탐색) (0) | 2021.10.03 |
---|---|
카카오 인턴십 3]표 편집 (이중 연결 리스트) (0) | 2021.09.01 |
22116 창영이와 퇴근[priority queue,Binary Search] (0) | 2021.08.18 |
19584 난개발 (누적합,TreeSet) (0) | 2021.06.30 |
1339 단어수학 (0) | 2021.02.22 |