# 5、背包问题 &01背包、完全背包

# AcWing 873. 欧拉函数 - AcWing

# AcWing 874. 筛法求欧拉函数

01背包问题 公式dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i])

# 注意优化一维dp时注意状态转移的先后顺序i和i-1

# 就是看谁先被算到,谁就作为i-1状态

import java.util.*;
import java.util.concurrent.LinkedTransferQueue;

//ACWing
public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        main.init();
    }

    //容斥原理
    int N = 1010;
    int dp[]=new int[N];
    int vs[]=new int[N];
    //vs表示体积
    int ws[]=new int[N];
    //ws表示价值
    int n, m;
    //n是n个物品
    //m是背包容量
    int bag(){
        for (int i = 1; i <= n; i++) {
            for (int j = m;j>=vs[i]; j--) {
                dp[j]=Math.max(dp[j],dp[j-vs[i]]+ws[i]);
            }
        }
        return dp[m];
    }
    void init() {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 1; i <= n; i++) {
            vs[i]= sc.nextInt();
            ws[i]= sc.nextInt();
        }
        int res=bag();
        System.out.println(res);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

完全背包问题 公式dp[i][j]=max(dp[i-1][j],dp[i][j-v[i]]+w[i])

import java.util.*;
import java.util.concurrent.LinkedTransferQueue;

//ACWing
public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        main.init();
    }
    int N = 1010;
    int dp[]=new int[N];
    int vs[]=new int[N];
    //vs表示体积
    int ws[]=new int[N];
    //ws表示价值
    int n, m;
    //n是n个物品
    //m是背包容量
    int bag(){
        for (int i = 1; i <= n; i++) {
            for (int j = 0;j<=m; j++) {
                if(j>=vs[i])
                    dp[j]=Math.max(dp[j],dp[j-vs[i]]+ws[i]);
            }
        }
        return dp[m];
    }
    void init() {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 1; i <= n; i++) {
            vs[i]= sc.nextInt();
            ws[i]= sc.nextInt();
        }
        int res=bag();
        System.out.println(res);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

多重背包问题

import java.util.*;
import java.util.concurrent.LinkedTransferQueue;

//ACWing
public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        main.init();
    }

    //容斥原理
    int N = 1010;
    int dp[][]=new int[N][N];
    int vs[]=new int[N];
    //vs表示体积
    int ws[]=new int[N];
    //ss表示物品最多的数量
    int ss[]=new int[N];
    //ws表示价值
    int n, m;
    //n是n个物品
    //m是背包容量
    int bag(){
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= m; j++) {
                for(int k=0;k<=ss[i]&& k * vs[i] <= j;k++){
                    dp[i][j]=Math.max(dp[i][j],dp[i-1][j-vs[i]*k]+ws[i]*k);
                }
            }
        }
        return dp[n][m];
    }
    void init() {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 1; i <= n; i++) {
            vs[i]= sc.nextInt();
            ws[i]= sc.nextInt();
            ss[i]= sc.nextInt();
        }
        int res=bag();
        System.out.println(res);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

多重背包问题Ⅱ

import java.util.*;
import java.util.concurrent.LinkedTransferQueue;

//ACWing
public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        main.init();
    }

    //容斥原理
    int N = 2010;
    int dp[][] = new int[N][N];
    int vs[] = new int[N];
    //vs表示体积
    int ws[] = new int[N];
    //ss表示物品最多的数量
    int ss[] = new int[N];
    //ws表示价值
    int n, m;

    //n是n个物品
    //m是背包容量
    void init() {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        int cnt = 0;
        for (int i = 1; i <= n; i++) {
            int v = sc.nextInt();
            int w = sc.nextInt();
            int s = sc.nextInt();
            int k = 1;
            while (k <= s) {
                cnt++;
                vs[cnt] = v * k;
                ws[cnt] = w * k;
                s -= k;
                k *= 2;
            }
            if (s > 0) {
                cnt++;
                vs[cnt] = v * s;
                ws[cnt] = w * s;
            }
        }
        n = cnt;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= m; j++) {
                dp[i][j] = dp[i - 1][j];
                if (j >= vs[i])
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - vs[i]] + ws[i]);
            }
        }
        System.out.println(dp[n][m]);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

分组背包问题

import java.sql.Statement;
import java.util.*;
import java.util.concurrent.LinkedTransferQueue;

//ACWing
public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        main.init();
    }

    //容斥原理
    int N = 1010;
    int dp[] = new int[N];
    int vs[][] = new int[N][N];
    //vs表示体积
    int ws[][] = new int[N][N];
    //ss表示物品最多的数量
    int ss[] = new int[N];
    //ws表示价值
    int n, m;

    void init() {
        Scanner sc = new Scanner(System.in);
        n=sc.nextInt();
        m= sc.nextInt();
        for (int i = 1; i <= n; i++) {
            ss[i] = sc.nextInt();
            for (int j = 0; j < ss[i]; j++) {
                vs[i][j] = sc.nextInt();
                ws[i][j] = sc.nextInt();
            }
        }

        for (int i = 1; i <= n; i ++ )
            for (int j = m; j >= 0; j -- )
                for (int k = 0; k < ss[i]; k ++ )
                    if (vs[i][k] <= j)
                        dp[j] = Math.max(dp[j], dp[j - vs[i][k]] + ws[i][k]);
        System.out.println(dp[m]);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42