您的位置:首页 > 编程语言 > Java开发

动态规划之背包问题(JAVA)

2017-12-18 21:59 204 查看
背包问题之前的C语言版本已经将思路解析的差不多,虽然还有些许错误需要改正,但大体思路是正确的,需要的读者请参阅动态规划之背包问题(C语言)

背包问题本身就是典型的动态规划问题,所以这里只给出动态规划的算法。

0-1背包

思路一:常规做法

import java.util.Scanner;

public class Main {
static Scanner in = new Scanner(System.in);
static int[] v,w;
static int[][] d;
static int n, c;
public static void main(String[] args) {
n = in.nextInt();
c = in.nextInt();
v = new int[n+1];
w = new int[n+1];
d = new int[c+1][c+1];
for (int i = 1; i <= n; i++) {
v[i] = in.nextInt();
w[i] = in.nextInt();
}
/**
* d(i, j) = max{d(i+1, j), d(i+1, j - V[i]) + W[i]}
* d(i, j)表示把第i, i+1, i+2...n个物品装到容量为 j 的背包中的最大总重量
* 所以i必须逆序, j无所谓
* */
for(int i = n; i >= 1; i--) {
for(int j = 0; j <= c; j++) {
d[i][j] = (i==n ? 0 : d[i+1][j]);
if(j >= v[i]) {
d[i][j] = Math.max(d[i][j],d[i+1][j-v[i]]+w[i]);
}
}
}
System.out.println(d[1][c]);
}
}


思路二:滚动数组,在输入数据的时候就进行处理

import java.util.Scanner;

public class Main {
static Scanner in = new Scanner(System.in);
static int[] v,w;
static int[][] d;
static int n, c;
public static void main(String[] args) {
n = in.nextInt();
c = in.nextInt();
v = new int[n+1];
w = new int[n+1];
d = new int[c+1][c+1];
/**
* d(i, j) = max{d(i-1, j), d(i-1, j - V[i]) + W[i]}
* d(i, j)表示把第前 i 个物品物品装到容量为 j 的背包中的最大总重量
* */
for(int i = 1; i <= n; i++) {
int v = in.nextInt();
int w = in.nextInt();
for(int j = 0; j <= c; j++) {
d[i][j] = (i==1 ? 0 : d[i-1][j]);
if(j >= v) {
d[i][j] = Math.max(d[i][j],d[i-1][j-v]+w);
}
}
}
System.out.println(d
[c]);
}
}


思路三:用一维数组实现

import java.util.Scanner;

class Main {
Scanner in = new Scanner(System.in);
static int[] w, v, d;
static int n, c;
public static void main(String[] args) {
/*v为背包容量, n为物品件数*/
n = in.nextInt();
c = in.nextInt();
w = new int[n+1];
v = new int[n+1];
d = new int[c+1];
/*w为物品重量数组, v为物品价值数组*/
for (int i = 1; i <= n; i++) {
w[i] = in.nextInt();
v[i] = in.nextInt();
}
for(int i = 1; i <= n; i++) {
//一维数组实现二次循环中必须用倒序
for(int j = c; j >= w[i]; j--) {
d[j] = Math.max(d[j], d[j - w[i]] + v[i]);
}
}
System.out.println(d[c]);
}
}


思路四:最简单版

import java.util.Scanner;

public class Main {
static Scanner in = new Scanner(System.in);
static int[] v, w, d;
static int n, c;
public static void main(String[] args) {
n = in.nextInt();
c = in.nextInt();
v = new int[n+1];
w = new int[n+1];
d = new int[c+1];

for (int i = 1; i <= n; i++) {
int v = in.nextInt();
int w = in.nextInt();
for (int j = c; j >= 0; j--) {
if (j >= v) {
d[j] = Math.max(d[j], d[j-v] + w);
}
}
}
System.out.println(d[c]);
}
}



d70e
全背包

用二维数组实现

import java.util.Scanner;

class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
/*v为背包容量, n为物品件数*/
int v = input.nextInt();
int n = input.nextInt();
int[] weight = new int[n+1];
int[] value = new int[n+1];
int[][] fa = new int[n+1][v+1];
/*weight为物品重量数组, value为物品价值数组*/
for (int i = 1; i <= n; i++) {
weight[i] = input.nextInt();
value[i] = input.nextInt();
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= v; j++) {
for(int k = 0; k * weight[i] <= j; k++) {
fa[i][j] = Math.max(fa[i][j], fa[i - 1][j - k * weight[i]] + k * value[i]);
}
}
}
System.out.println(fa
[v]);
}
}


用一维数组实现

import java.util.Scanner;

class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
/*v为背包容量, n为物品件数*/
int v = input.nextInt();
int n = input.nextInt();
int[] weight = new int[n+1];
int[] value = new int[n+1];
int[] fa = new int[v+1];
/*weight为物品重量数组, value为物品价值数组*/
for (int i = 1; i <= n; i++) {
weight[i] = input.nextInt();
value[i] = input.nextInt();
}
for(int i = 1; i <= n; i++) {
//完全背包问题一维数组实现二次循环必须正序
for(int j = weight[i]; j <= v; j++) {
fa[j] = Math.max(fa[j], fa[j - weight[i]] + value[i]);
}
}
System.out.println(fa[v]);
}
}


多重背包

用二维数组实现

import java.util.Scanner;

class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
/*v为背包容量, n为物品件数*/
int v = input.nextInt();
int n = input.nextInt();
int[] weight = new int[n+1];
int[] value = new int[n+1];
int[] num = new int[n+1];
int[][] fa = new int[n+1][v+1];
/*weight为物品重量数组, value为物品价值数组*/
for (int i = 1; i <= n; i++) {
weight[i] = input.nextInt();
value[i] = input.nextInt();
num[i] = input.nextInt();
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= v; j++) {
for(int k = 1; k <= num[i] && k * weight[i] <= j; k++) {
fa[i][j] = Math.max(fa[i-1][j], fa[i - 1][j - k * weight[i]] + k * value[i]);
}
}
}
System.out.println(fa
[v]);
}
}


用一维数组实现

import java.util.Scanner;

class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
/*v为背包容量, n为物品件数*/
int v = input.nextInt();
int n = input.nextInt();
int[] weight = new int[n+1];
int[] value = new int[n+1];
int[] num = new int[n+1];
int[] fa = new int[v+1];
/*weight为物品重量数组, value为物品价值数组*/
for (int i = 1; i <= n; i++) {
weight[i] = input.nextInt();
value[i] = input.nextInt();
num[i] = input.nextInt();
}
for (int i = 1; i <= n; i++) {
for (int j = v; j >= 1; j--) {
for (int k = 1; k <=num[i] && k * weight[i] <= j; k++) {
fa[j] = Math.max(fa[j], fa[j - k * weight[i]] + k * value[i]);
}
}
}
System.out.println(fa[v]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息