算法学习-三种背包问题模板(JAVA实现)

本文最后更新于:January 26, 2022 pm

纸上得来终觉浅,绝知此事要躬行。路漫漫其修远兮,吾将上下而求索!知识是经过历史的巨人沉淀下来的,别总想着自己能够快速学会,多花点时间去看看,也许会发现些不同的东西。你能快速学会的、觉得简单的东西,对于别人来说也是一样的。人外有人,天外有天。当努力到达了一定的程度,幸运自会与你不期而遇。

目录

01背包

每件物品只能选或者不选。

题目练习

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import java.io.*;
import java.math.BigInteger;
import java.util.*;


/**
* @Author DragonOne
* @Date 2021/12/5 21:27
* @墨水记忆 www.tothefor.com
*/
public class Main {
public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
public static Scanner sc = new Scanner(System.in);

public static int maxd = 100000+7;
public static int INF = 0x3f3f3f3f;
public static int mod = 998244353;
public static int[] dp = new int[maxd]; //最大价值
public static int[] w = new int[maxd]; //每件物品的体积
public static int[] v = new int[maxd]; //每件物品的价值


public static void main(String[] args) throws Exception {

int n = nextInt(); //n件物品
int m = nextInt(); //给出的体积
for(int i=1;i<=n;++i) {
w[i] = nextInt();
v[i] = nextInt();
}
for(int i=1;i<=n;++i){
for(int j=m;j>=w[i];--j){ //与完全背包的区别
dp[j] = Math.max(dp[j],dp[j-w[i]]+v[i]);
}
}
System.out.println(dp[m]);

closeAll();
}

public static void cinInit(){
cin.wordChars('a', 'z');
cin.wordChars('A', 'Z');
cin.wordChars(128 + 32, 255);
cin.whitespaceChars(0, ' ');
cin.commentChar('/');
cin.quoteChar('"');
cin.quoteChar('\'');
cin.parseNumbers(); //可单独使用来还原数字
}

public static int log(int x){ //log方法是以2为底,求x的对数。java自带的log是以e为底的
return (int) (Math.log(x)/Math.log(2));
}

public static int nextInt() throws Exception{
cin.nextToken();
return (int) cin.nval;
}
public static long nextLong() throws Exception{
cin.nextToken();
return (long) cin.nval;
}
public static double nextDouble() throws Exception{
cin.nextToken();
return cin.nval;
}
public static String nextString() throws Exception{
cin.nextToken();
return cin.sval;
}
public static void closeAll() throws Exception {
cout.close();
in.close();
out.close();
}
}

完全背包

每件物品都有无限件。

题目练习

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;


/**
* @Author DragonOne
* @Date 2021/12/5 21:27
* @墨水记忆 www.tothefor.com
*/
public class Main {
public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
public static Scanner sc = new Scanner(System.in);

public static int maxd = 100000+7;
public static int INF = 0x3f3f3f3f;
public static int mod = 998244353;
public static int[] dp = new int[maxd]; //最大价值
public static int[] w = new int[maxd]; //每件物品的体积
public static int[] v = new int[maxd]; //每件物品的价值


public static void main(String[] args) throws Exception {

int n = nextInt();
int m = nextInt();
for(int i=1;i<=n;++i){
w[i] = nextInt();
v[i] = nextInt();
}
for(int i=1;i<=n;++i){
for(int j=w[i];j<=m;++j){ //与01背包的区别
dp[j]=Math.max(dp[j],dp[j-w[i]]+v[i]);
}
}
System.out.println(dp[m]);
closeAll();
}

public static void cinInit(){
cin.wordChars('a', 'z');
cin.wordChars('A', 'Z');
cin.wordChars(128 + 32, 255);
cin.whitespaceChars(0, ' ');
cin.commentChar('/');
cin.quoteChar('"');
cin.quoteChar('\'');
cin.parseNumbers();
}
public static int nextInt() throws Exception {
cin.nextToken();
return (int) cin.nval;
}
public static long nextLong() throws Exception {
cin.nextToken();
return (long) cin.nval;
}
public static double nextDouble() throws Exception {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws Exception {
cin.nextToken();
return cin.sval;
}
public static void closeAll() throws Exception {
cout.close();
in.close();
out.close();
}
}

多重背包(二进制优化)

每一件物品都有一定的数量。二进制优化后就转化为了求01背包问题。

题目练习1

题目练习2

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;


/**
* @Author DragonOne
* @Date 2021/12/5 21:27
* @墨水记忆 www.tothefor.com
*/
public class Main {
public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
public static Scanner sc = new Scanner(System.in);

public static int maxd = 100000+7;
public static int INF = 0x3f3f3f3f;
public static int mod = 998244353;
public static int[] dp = new int[maxd]; //最大价值
public static int[] w = new int[maxd]; //每件物品的体积
public static int[] v = new int[maxd]; //每件物品的价值
public static int g = 1;


public static void main(String[] args) throws Exception {

int n = nextInt();
int m = nextInt();
for(int i=1;i<=n;++i){
int a = nextInt(); //体积
int b = nextInt(); //价值
int c = nextInt(); //数量
for(int j=1;j<=c;j<<=1){
w[g]=j*a;
v[g++]=j*b;
c-=j;
}
if(c>0){
w[g]=c*a;
v[g++]=c*b;
}
}
for(int i=1;i<=g;++i){
for(int j=m;j>=w[i];--j){
dp[j]=Math.max(dp[j],dp[j-w[i]]+v[i]);
}
}
System.out.println(dp[m]);
closeAll();
}

public static void cinInit(){
cin.wordChars('a', 'z');
cin.wordChars('A', 'Z');
cin.wordChars(128 + 32, 255);
cin.whitespaceChars(0, ' ');
cin.commentChar('/');
cin.quoteChar('"');
cin.quoteChar('\'');
cin.parseNumbers();
}
public static int nextInt() throws Exception {
cin.nextToken();
return (int) cin.nval;
}
public static long nextLong() throws Exception {
cin.nextToken();
return (long) cin.nval;
}
public static double nextDouble() throws Exception {
cin.nextToken();
return cin.nval;
}
public static String nextString() throws Exception {
cin.nextToken();
return cin.sval;
}
public static void closeAll() throws Exception {
cout.close();
in.close();
out.close();
}
}

代码可交两个题。