Closed KodaHye closed 3 weeks ago
Knapsack
사용해도 무리가 없음int[] dp = new int[100];
// 중복 선택이 불가능한 0-1 Knapsack
for (int i = 0; i < n; i++) {
for (int j = 99; j >= cost[i]; j--) {
dp[j] = Math.max(dp[j], dp[j - cost[i]] + get[i]);
}
}
System.out.println(dp[99]);
O(N^2)
가능0-1 배낭 문제
2차원 배열
사용K=99
-int[] weight
: 체력, int[] value
: 기쁨
int[][] dp = new int[N+1][K+1];
for(int i=1; i<=N; i++){
for(int j=1; j<=K; j++){
if(weight[i]<= j) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i-1][j - (weight[i])] + value[i]);
}
else dp[i][j] = dp[i-1][j]; // 인사하지 않는 경우
}
}
O(N^2)
가능dp[health]
가 아닌, dp[health-1]
값 사용 int[] dp = new int[health + 1];
for (int i = 1; i <= N; i++) {
for (int j = health; j >= hp[i]; j--) {
dp[j] = Math.max(dp[j], dp[j - hp[i]] + happy[i]);
}
}
System.out.println(dp[health-1]);
=> 완전탐색도 가능
0-1 Knapsack
dp[j]
: 체력이 j가 될 때, 최대 기쁨가치
j>h[i]
: j가 체력보다 클 때만 인사하기
for(int i=1; i<N+1; i++) {
for(int j=MAX_HP; j>h[i]; j--) {
dp[j] = Math.max(dp[j], dp[j-h[i]]+v[i]);
}
}
사람의 수 <= 20
세준이의 체력 100
1) 완탐: 사람을 선택하는 모든 경우를 고려했을 때, 2^20
으로 문제 풀이 가능
2) Knapsack: 사람의 수 × 100
으로 문제 풀이 가능
int[] dp = new int[101]
dp[i]
: 체력을 i
만큼 사용했을 때, 얻을 수 있는 최대 기쁨int[] W
: 각각의 사람에게 인사를 할 때, 잃는 체력 (무게)int[] V
: 인사를 할 때 얻는 기쁨 (가치)for(int i = 1; i < N + 1; i++) {
for(int k = 100; k > W[i]; k--) {
dp[k] = Math.max(dp[k], dp[k - W[i]] + V[i]);
}
}
알고리즘: dp > 0-1냅색 알고리즘(중복X)
N(≤ 20)
, 0<= 체력,기쁨 <= 100
0-1냅색 알고리즘으로 풀이 시 N*100
final int MAX_STAMINA = 100;
int[] dp = new int[MAX_STAMINA+1]; //dp[체력]= 최대 기쁨
for(int i = 1; i < N+1; i++){
for(int stamina=MAX_STAMINA; stamina > 0; stamina--) {
int total = stamina-exhaustion[i];
if (total > 0) {
dp[stamina] = Math.max(dp[stamina], dp[total] + happy[i]);
}
}
}
으아!!!!!!!!!!!!!!!!!!!!!나는 정말 멍청이에요!!!!!!!!!!!!!!!!! 오늘 냅색 리뷰했는데 왜 바로 응용을 못하는건지🤦♀️💦😭
dp[?] = 최대기쁨
얻고자하는 값을 얻기 위해 어떤 상태가 되어야하는지 기준 잡는게 어렵네요..