𝘚𝘭𝘰𝘸 𝘣𝘢𝘡 𝘴𝘡𝘦𝘒π˜₯𝘺

[λ°±μ€€] 9465번: μŠ€ν‹°μ»€ - C++ λ³Έλ¬Έ

μ½”λ”©ν…ŒμŠ€νŠΈ μ€€λΉ„/λ°±μ€€

[λ°±μ€€] 9465번: μŠ€ν‹°μ»€ - C++

.23 2021. 7. 27. 01:30
문제

μƒκ·Όμ΄μ˜ 여동생 상λƒ₯μ΄λŠ” λ¬Έλ°©κ΅¬μ—μ„œ μŠ€ν‹°μ»€ 2n개λ₯Ό κ΅¬λ§€ν–ˆλ‹€. μŠ€ν‹°μ»€λŠ” κ·Έλ¦Ό (a)와 같이 2ν–‰ nμ—΄λ‘œ λ°°μΉ˜λ˜μ–΄ μžˆλ‹€. 상λƒ₯μ΄λŠ” μŠ€ν‹°μ»€λ₯Ό μ΄μš©ν•΄ 책상을 κΎΈλ―Έλ €κ³  ν•œλ‹€.

상λƒ₯이가 κ΅¬λ§€ν•œ μŠ€ν‹°μ»€μ˜ ν’ˆμ§ˆμ€ 맀우 쒋지 μ•Šλ‹€. μŠ€ν‹°μ»€ ν•œ μž₯을 λ–Όλ©΄, κ·Έ μŠ€ν‹°μ»€μ™€ 변을 κ³΅μœ ν•˜λŠ” μŠ€ν‹°μ»€λŠ” λͺ¨λ‘ μ°’μ–΄μ Έμ„œ μ‚¬μš©ν•  수 μ—†κ²Œ λœλ‹€. 즉, λ—€ μŠ€ν‹°μ»€μ˜ μ™Όμͺ½, 였λ₯Έμͺ½, μœ„, μ•„λž˜μ— μžˆλŠ” μŠ€ν‹°μ»€λŠ” μ‚¬μš©ν•  수 μ—†κ²Œ λœλ‹€.

λͺ¨λ“  μŠ€ν‹°μ»€λ₯Ό 뢙일 수 μ—†κ²Œλœ 상λƒ₯μ΄λŠ” 각 μŠ€ν‹°μ»€μ— 점수λ₯Ό 맀기고, 점수의 합이 μ΅œλŒ€κ°€ 되게 μŠ€ν‹°μ»€λ₯Ό λ–Όμ–΄λ‚΄λ €κ³  ν•œλ‹€. λ¨Όμ €, κ·Έλ¦Ό (b)와 같이 각 μŠ€ν‹°μ»€μ— 점수λ₯Ό 맀겼닀. 상λƒ₯이가 λ—„ 수 μžˆλŠ” μŠ€ν‹°μ»€μ˜ 점수의 μ΅œλŒ“κ°’μ„ κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€. 즉, 2n개의 μŠ€ν‹°μ»€ μ€‘μ—μ„œ 점수의 합이 μ΅œλŒ€κ°€ λ˜λ©΄μ„œ μ„œλ‘œ 변을 곡유 ν•˜μ§€ μ•ŠλŠ” μŠ€ν‹°μ»€ 집합을 ꡬ해야 ν•œλ‹€.

μœ„μ˜ 그림의 κ²½μš°μ— μ μˆ˜κ°€ 50, 50, 100, 60인 μŠ€ν‹°μ»€λ₯Ό κ³ λ₯΄λ©΄, μ μˆ˜λŠ” 260이 되고 이 것이 μ΅œλŒ€ μ μˆ˜μ΄λ‹€. κ°€μž₯ 높은 점수λ₯Ό κ°€μ§€λŠ” 두 μŠ€ν‹°μ»€ (100κ³Ό 70)은 변을 κ³΅μœ ν•˜κΈ° λ•Œλ¬Έμ—, λ™μ‹œμ— λ—„ 수 μ—†λ‹€.

 

μž…λ ₯

첫째 쀄에 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ˜ 개수 Tκ°€ 주어진닀. 각 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ˜ 첫째 μ€„μ—λŠ” n (1 ≤ n ≤ 100,000)이 주어진닀. λ‹€μŒ 두 μ€„μ—λŠ” n개의 μ •μˆ˜κ°€ 주어지며, 각 μ •μˆ˜λŠ” κ·Έ μœ„μΉ˜μ— ν•΄λ‹Ήν•˜λŠ” μŠ€ν‹°μ»€μ˜ μ μˆ˜μ΄λ‹€. μ—°μ†ν•˜λŠ” 두 μ •μˆ˜ μ‚¬μ΄μ—λŠ” 빈 칸이 ν•˜λ‚˜ μžˆλ‹€. μ μˆ˜λŠ” 0보닀 ν¬κ±°λ‚˜ κ°™κ³ , 100보닀 μž‘κ±°λ‚˜ 같은 μ •μˆ˜μ΄λ‹€. 

 

좜λ ₯

각 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€ λ§ˆλ‹€, 2n개의 μŠ€ν‹°μ»€ μ€‘μ—μ„œ 두 변을 κ³΅μœ ν•˜μ§€ μ•ŠλŠ” μŠ€ν‹°μ»€ 점수의 μ΅œλŒ“κ°’μ„ 좜λ ₯ν•œλ‹€.


DPλ₯Ό μ‚¬μš©ν•˜μ—¬ ν’€ 수 μžˆλŠ” 문제.

μŠ€ν‹°μ»€λ“€μ˜ μ μˆ˜κ°€ μ΅œλŒ€κ°€ 될 수 μžˆλŠ” 경우λ₯Ό 생각할 λ•Œ, μ„œλ‘œ 변을 곡유 ν•˜μ§€ μ•ŠλŠ” κ·œμΉ™μœΌλ‘œ 인해 μƒν•˜μ’Œμš°λ‘œ ν•œ μΉΈμ”© μ›€μ§μ΄λŠ” 것이 λΆˆκ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— λŒ€κ°μ„ μœΌλ‘œ μ›€μ§μ΄κ±°λ‚˜ ν•œ 칸을 λ›°μ–΄λ„˜μ–΄ μ΄λ™ν•˜λŠ” 경우 등을 κ³ λ €ν•΄λ³Ό 수 μžˆλ‹€. κ·ΈλŸ¬λ‚˜ ν•œ 칸을 λ›°μ–΄λ„˜μ–΄ μ΄λ™ν•˜λŠ” κ²½μš°λŠ” λŒ€κ°μ„  μœ„/μ•„λž˜λ‘œ 두 번 μ›€μ§μ΄λŠ” κ²½μš°λ³΄λ‹€ μ μˆ˜κ°€ λ°˜λ“œμ‹œ μž‘κ²Œ λ‚˜μ˜€κΈ° λ•Œλ¬Έμ—, 결과적으둜 이동할 수 μžˆλŠ” κ²½λ‘œλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

0번째 쀄 μ‹œμž‘ κΈ°μ€€

첫번째 쀄을 κΈ°μ€€μœΌλ‘œ λŒ€κ°μ„  λ°”λ‘œ μ•„λž˜μ˜ μŠ€ν‹°μ»€λ₯Ό μ„ νƒν•˜κ±°λ‚˜, ν•œμΉΈ 더 λ–¨μ–΄μ ΈμžˆλŠ” λŒ€κ°μ„  μ•„λž˜μ˜ μŠ€ν‹°μ»€λ₯Ό μ„ νƒν•˜λŠ” λ°©λ²•μœΌλ‘œ λ‚˜λˆŒ 수 μžˆλ‹€. μ„Έ μΉΈ 이상 떨어진 κ²½μš°λΆ€ν„°λŠ” 더 큰 점수λ₯Ό λ‚Ό 수 μžˆλŠ” 방법이 μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έμ— 이 두가지 경우만 μƒκ°ν•˜λ„λ‘ ν•œλ‹€. κ·Έλ¦¬ν•˜μ—¬ i번째 μΉΈκΉŒμ§€ μ™”μ„λ•Œ κ°€μž₯ 큰 μ μˆ˜λŠ” [i - 1]μΉΈ κΉŒμ§€μ˜ μ μˆ˜λ‚˜ [i - 2]μΉΈ κΉŒμ§€μ˜ 점수 합을 λΉ„κ΅ν•˜μ—¬ 더 큰 값을 μ„ νƒν•œ λ’€ ν•΄λ‹Ή 칸의 점수λ₯Ό λ”ν•œλ‹€. μ΅œμ’…μ μœΌλ‘œ 0번째 μ€„μ—μ„œ μ‹œμž‘ν•˜λŠ” κ²½μš°μ™€ 1번째 μ€„μ—μ„œ μ‹œμž‘ν•˜λŠ” 경우λ₯Ό λΉ„κ΅ν•΄μ„œ 더 큰 값이 결과값이 λœλ‹€. 점화식은 λ‹€μŒκ³Ό κ°™λ‹€.

 

D[0][i] = sticker[0][i] + MAX(D[1][i - 1], D[1][i - 2])

D[1][i] = sticker[1][i] + MAX(D[0][i - 1], D[0][i - 2])

 

λ¬Έμ œλŠ” Bottom-up λ°©μ‹μœΌλ‘œ ν’€μ—ˆλ‹€.

μ½”λ“œ
#include <cstdio>
#define MAX 100001

int DP(int num);

int main(void) {
    int t;
    scanf("%d", &t);
    for(int i = 0; i < t; i++) {
        int n;
        scanf("%d", &n);
        printf("%d\n", DP(n));
    }
    return 0;
}

int DP(int num) {
    int data[2][MAX] = { 0 }; // μ‹€μ œ μŠ€ν‹°μ»€μ˜ 점수 μ €μž₯
    int memo[2][MAX] = { 0 }; // λˆ„μ λœ 점수 ν•© μ €μž₯

    for(int i = 0; i < 2; i++) {
        for(int j = 1; j <= num; j++) {
            scanf("%d", &data[i][j]);
        }
    }

    memo[0][1] = data[0][1];    // case 1. 1ν–‰ 1μ—΄λΆ€ν„° μ‹œμž‘
    memo[1][1] = data[1][1];    // case 2. 2ν–‰ 1μ—΄λΆ€ν„° μ‹œμž‘

    for(int i = 2; i <= num; i++) {
        memo[0][i] = data[0][i] + (memo[1][i - 1] > memo[1][i - 2] ? memo[1][i - 1] : memo[1][i - 2]);
        memo[1][i] = data[1][i] + (memo[0][i - 1] > memo[0][i - 2] ? memo[0][i - 1] : memo[0][i - 2]);
    }

    return memo[0][num] > memo[1][num] ? memo[0][num] : memo[1][num];
}
Comments