[ACWing] 7. 혼합 배낭 문제

제목 주소 :

https://www.acwing.com/problem/content/7/

NN 있음N 개 항목과 1 개 용량은VV입니다.V 의 배낭. 세 가지 유형의 항목이 있습니다. 첫 번째 항목은1개만 사용할 수 있습니다.1 회 (0 − 1 0-101 개 ) 배낭, 상품의 제 2 유형에는 제한 시간 (전체 배낭)를 사용할 수 있으며 상품의 세번째 유형은 기껏해야 사용할 수SI s_i에스나는Times (여러 배낭), 각 볼륨은 vi v_i입니다.V나는, 값은 wi w_i입니다.w나는. 배낭에 어떤 아이템이 적재되었는지 확인하여 아이템의 총 부피가 배낭의 용량을 초과하지 않고 총 값이 가장 큽니다. 최대 값을 출력합니다.

입력 형식 :
첫 번째 줄에 두 개의 정수, NNN ,VV공백으로 구분 된 V 는 각각 물체의 수와 배낭의 부피를 나타냅니다. 다음은NN입니다N 라인, 라인 당 3 개의 정수vi, wi, si v_i, w_i, s_iV나는,w나는,에스나는, 공백으로 구분하여 각각 ii품목의 양, 가치 및 수량 i . si = − 1 s_i = −1에스나는=1ii를의미합니다.유형 I 항목 만 사용할 수 있습니다1 11 차;si = 0 s_i = 0에스나는=0ii를의미합니다.유형 i 항목은 무제한으로 사용할 수 있습니다.si> 0 s_i> 0에스나는>0ii를의미합니다.i 유형의 항목은si s_i를사용할 수 있습니다.에스나는타임스

출력 형식 :
최대 값을 나타내는 정수를 출력합니다.

데이터 범위 :
0 <N, V ≤ 1000 0 <N, V ≤ 10000<N ,V1 0 0 0
0 <VI, WI ≤ 1,000 0 <V_I, w_i≤10000<V나는,w나는1 0 0 0
- SI ≤ ≤ 1,000 -1≤si≤1000 11s 나는1 0 0 0

아이디어는 여전히 동적 프로그래밍이고 상태 표현은 f [i] [j] f [i] [j]f [ i ] [ j ] , 즉 전자iii 항목에서 선택하고 볼륨은jj를초과하지 않습니다j 섹션ii에 따른 최대 값i 항목의 범주를 선택하거나 선택하지 않습니다. 옵션1 s_i = -1 - SI =에스나는=1 ,0 − 1 0-1을사용할 수 있습니다.01 백팩 재귀; forsi = 0 s_i = 0에스나는=0 , 전체 배낭에서 재귀 적으로 사용할 수 있습니다. forsi> 0 s_i> 0에스나는>0 , 여러 배낭을 사용하여 재귀 적으로 사용할 수 있지만 시간 초과를 방지하기 위해 여기에 바이너리 최적화를 추가해야합니다. 참조 :
1,0 − 1 0-101 백팩 :https://blog.csdn.net/qq_46105170/article/details/113668186;
2. 전체 백팩 :https://blog.csdn.net/qq_46105170/article/details/113834289;
3. 다중 바이너리 최적화 백팩 버전 :https://blog.csdn.net/qq_46105170/article/details/113840962.

코드 쇼 :

#include <iostream>
using namespace std;

const int N = 1010;
int n, m;
int f[N];

int main() {
    
    
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
    
    
        int v, w, s;
        cin >> v >> w >> s;
        if (s == 0) 
            for (int j = v; j <= m; j++)
                f[j] = max(f[j], f[j - v] + w);
        else {
    
    
        	// 0-1背包问题可以看成是物品只有1个的多重背包问题
            if (s == -1) s = 1;
            // 二进制优化
            for (int k = 1; k <= s; k *= 2) {
    
    
                for (int j = m; j >= k * v; j--) 
                    f[j] = max(f[j], f[j - k * v] + k * w);
                s -= k;
            }

            if (s)
                for (int j = m; j >= s * v; j--)
                    f[j] = max(f[j], f[j - s * v] + s * w);
        }
    }    

    cout << f[m] << endl;

    return 0;
}

시간 복잡도 O ((N − k) + ∑ i = 1k log ⁡ si)) O (V ((Nk) + \ sum _ (i = 1) ^ k \ log s_i))O ( V ( ( Nk )+나는 = 1케이싸다 g에스나는) ) , 어디kkksi s_i를사용할 수 있습니다.에스나는항목 유형 수 (즉, 이진으로 최적화 할 항목 유형 수), 공백 O (V) O (V)O ( V )

추천

출처blog.csdn.net/qq_46105170/article/details/114298331