알고리즘/baekjoon

[1535번] 안녕

sunm2n 2025. 8. 1. 19:31

문제링크 : https://www.acmicpc.net/problem/1535

 

 

1. 문제 인식

사람 N명에게 인사를 할 수 있다.

인사하면 hp[i]만큼 체력을 잃고 happy[i]만큼 기쁨을 얻는다.

체력이 0 이하가 되면 죽는다 (즉, 체력은 최소 1이어야 한다).

목표: 체력이 1 이상 남도록 하면서 얻을 수 있는 기쁨의 최대값 구하기.

 

즉, 각 사람에게 인사를 "할지 말지" 선택해야 함
선택의 문제 → 부분 문제의 최적해 → 동적 계획법(DP) 를 사용하자

 

 

이 문제는 0/1 Knapsack 문제와 유사하다 

 

Knapsack 요소 이 문제의 대응 항목

무게 (비용) 체력 소모 (hp[i])
가치 (얻는 것) 기쁨 (happy[i])
최대 무게 체력 제한 (100 이하)

 

사람마다 한 번만 인사할 수 있으므로 0/1 Knapsack이다.

 

 

2. 상태 정의 (DP 배열 정의)

 

dp[i] = 체력이 i일 때 얻을 수 있는 최대 기쁨

인사를 해서 체력이 i가 됐을 때, 그때까지의 최대 기쁨을 저장

초기 상태: 아무것도 안 한 상태 → dp[100] = 0 (체력 100, 기쁨 0)

 

 

3. 점화식 설계

 

사람 i를 고려할 때:

현재 체력이 j일 때

그 사람에게 인사하면 hp[i]만큼 체력을 잃고, happy[i]를 얻는다.

체력이 0이 되면 죽으므로 → j - hp[i] > 0일 때만 인사 가능

 

for (int i = 0; i < N; i++) {
    for (int j = 100; j >= hp[i]; j--) {
        if (j - hp[i] > 0) { // 체력이 hp[i] 이상이어야 인사 가능
            dp[j] = Math.max(dp[j], dp[j - hp[i]] + happy[i]);
        }
    }
}

 

역순 순회하는 이유: 같은 i에 대해 중복 선택을 방지하기 위해 (0/1 Knapsack 특성)

 

 

4. 최종 결과 구하기

int max_happy = 0;
for (int i = 1; i <= 100; i++) {
    max_happy = Math.max(max_happy, dp[i]);
}

 

체력이 1 이상인 상태 중에서 가장 큰 기쁨값을 찾으면 된다.

 

 

5. 전체코드

 

package DynamicPrograming;

import java.util.Scanner;

public class _1535 {
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        int N = sc.nextInt(); // 사람 수
        int []hp = new int[N]; // 인사를 할 때 마다 잃는 체력
        int []happy = new int[N]; // 인사를 할 때마다 얻는 기쁨

        for (int i = 0; i < N; i++) {
            hp[i] = sc.nextInt();
        }

        for (int i = 0; i < N; i++) {
            happy[i] = sc.nextInt();
        }

        int[] dp = new int[101]; // 체력은 최대 100

        for (int i = 0; i < N; i++) {
            for (int j = 100; j >= hp[i]; j--) {
                if (j - hp[i] > 0) { // 체력이 hp[i] 이상이어야 인사 가능
                    dp[j] = Math.max(dp[j], dp[j - hp[i]] + happy[i]);
                }
            }
        }

        int max_happy = 0;
        for (int i = 1; i <= 100; i++) {
            max_happy = Math.max(max_happy, dp[i]);
        }

        System.out.println(max_happy);
    }
}

'알고리즘 > baekjoon' 카테고리의 다른 글

[1439번] 뒤집기  (0) 2025.11.06
[13371번] Dolphin  (0) 2025.10.21
[9465번] 스티커  (2) 2025.07.30
[11052번] 카드 구매하기  (0) 2025.07.16
[11054번] 가장 긴 바이토닉 부분 수열  (1) 2025.07.03