Closed KodaHye closed 3 weeks ago
DP
, Knapscak
Knapsack
int[] dp = new int[d + 1];
dp[0] = Integer.MAX_VALUE; // 최솟값을 찾기 위해 첫 시작은 최대로 초기화
// 중복 선택이 불가능한 0-1 Knapsack
for (int i = 0; i < p; i++) {
for (int j = d; j >= length[i]; j--) {
// j길이를 만들었을 때 가질 수 있는 파이프의 최대 넓이
dp[j] = Math.max(dp[j], Math.min(dp[j - length[i]], width[i]));
}
}
System.out.println(dp[d]);
문제가 신기했습니다
01냅색(중복X)
dp[i] = k
: 수도관 길이 j를 만들때 가능한 파이프의 최소용량 k최소값
을 선택해야함Math.min(dp[j - len[i]], cost[i])
: 새로운 파이프를 추가할때 수도관을 이루는 전체 파이프에서 최소값 갱신최소 파이프들 중 큰 값
을 선택해야함
-Math.max(dp[j], Math.min(dp[j - len[i]], cost[i]))
: 가능한 파이프 중 최대값을 골라, 최대 수도관 용량 구하기 int[] dp = new int[D + 1];
dp[0] = Integer.MAX_VALUE;
for (int i = 1; i <= P; i++) {
for (int j = D; j >= len[i]; j--) {
dp[j] = Math.max(dp[j], Math.min(dp[j - len[i]], cost[i]));
}
}
System.out.println(dp[D]);
O(N^2)
dp[0] = Integer.MAX_VALUE;
for(int i=1; i<=P; i++){
st = new StringTokenizer(br.readLine());
int L = Integer.parseInt(st.nextToken());
int C = Integer.parseInt(st.nextToken());
for(int j = D; j>= L; j--){
dp[j] = Math.max(dp[j], Math.min(C, dp[j-L]));
}
}
7 <= 거리 <= 100_000
1 <= 파이프의 개수 <= 350
거리 × 파이프의 개수 < 1억
(거의 1억에 가까움) 이내로 풀이해야 됨
dp[0] = Integer.MAX_VALUE
로 초기화for(int i = 1; i < P + 1; i++) {
for(int j = D; j >= pipes[i].l; j--) {
int min = Math.min(dp[j - pipes[i].l], pipes[i].c);
dp[j] = Math.max(dp[j], min);
}
}
=> O(D * P) 가능
0-1 Knapsack
dp[j]
: 길이가 j일 때 최대 수도관 용량
max(dp[j], i번째 파이프를 추가할 때 용량)
수도관 용량
: 길이 j를 이루는 파이프들의 용량 중 가장 작은 값
min( j-L[i]인 수도관 용량, i번째 용량)
dp[0] = Integer.MAX_VALUE
로 초기화7 ≤ D ≤ 100,000
1 ≤ P ≤ 350
냅색알고리즘으로 풀이 시 O(D*P)
10^6
으로 풀이가능dp[j] = Math.max(dp[j], Math.min(dp[j - len[i]], cost[i]));
수도관의 용량은 그것을 이루는 파이프들의 용량 중 최솟값 → 수도관의 용량 = 어떤 수도관을 만들었을 때 여러 파이프 구성 중에 용량이 가장 작은 값
Math.min(dp[j - len[i]], cost[i])
dp[j - len[i]]
현재 파이프를 추가하기 전 이전 상태에 대한 용량cost[i]
현재 파이프의 용량완성된 파이프들 중 가장 큰 용량을 구해야 한다. → 만들어진 여러개의 수도관 중 최대 용량 구하기 (수도관은 최소 1개 이상 만들 수 있음)
Math.max(dp[j], 최소 용량)