Poj-3624 背包问题
题目
解决代码
第一版:
import java.util.Scanner;
public class Main {
/**
* 有N件物品,有一个体积为V的背包
* 第i件物品的费用为c[i],价值是w[i];
* 问:如何价值最大
4 6
1 4
2 6
3 12
2 7
*/
public static int getMaxWorth(int N, int V, int[] c, int[] v) {
//记录放第 i 个物品时,空间为 j 时, 其最大价值
int[][] f = new int[N+1][V + 1];
//最大价值
int maxWorth = 0;
//如果不输入,默认就为0
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= V; j++) {
//如果空间足够放当前物品
if (j >= c[i - 1]) {
f[i][j] = f[i-1][j] > f[i-1][j - c[i - 1]] + v[i - 1] ? f[i-1][j] : f[i-1][j - c[i - 1]] + v[i - 1];
}else{
f[i][j]=f[i-1][j];
}
//System.out.println("放第"+i+"物品"+",空间为"+j+"时,其最大价值为"+f[i][j]);
}
if (maxWorth < f[i][V]) {
maxWorth = f[i][V];
}
}
return maxWorth;
}
public static void main(String[] args) {
//N为物品个数
// V为体积大小
int N,V;
int[] c,v;
Scanner scanner = new Scanner(System.in);
//依次输入物品个数和体积大小
N = scanner.nextInt();
V = scanner.nextInt();
c = new int[N];
v = new int[N];
//输入物品详情
for (int i = 0; i < N; i++) {
c[i] = scanner.nextInt();
v[i] = scanner.nextInt();
}
System.out.println(getMaxWorth(N, V, c, v));
}
}
输入:
4 6
1 4
2 6
3 12
2 7放第1物品,空间为1时,其最大价值为4
放第1物品,空间为2时,其最大价值为4
放第1物品,空间为3时,其最大价值为4
放第1物品,空间为4时,其最大价值为4
放第1物品,空间为5时,其最大价值为4
放第1物品,空间为6时,其最大价值为4
放第2物品,空间为1时,其最大价值为4
放第2物品,空间为2时,其最大价值为6
放第2物品,空间为3时,其最大价值为10
放第2物品,空间为4时,其最大价值为10
放第2物品,空间为5时,其最大价值为10
放第2物品,空间为6时,其最大价值为10
放第3物品,空间为1时,其最大价值为4
放第3物品,空间为2时,其最大价值为6
放第3物品,空间为3时,其最大价值为12
放第3物品,空间为4时,其最大价值为16
放第3物品,空间为5时,其最大价值为18
放第3物品,空间为6时,其最大价值为22
放第4物品,空间为1时,其最大价值为4
放第4物品,空间为2时,其最大价值为7
放第4物品,空间为3时,其最大价值为12
放第4物品,空间为4时,其最大价值为16
放第4物品,空间为5时,其最大价值为19
放第4物品,空间为6时,其最大价值为23
但是当把此代码提交上去后会出现内存不足的情况。Memory Limit Exceeded
当时就考虑了下可能是因为创建数组 int[][] f = new int[N+1][V + 1]; 过大的原因
因为我们只需要记录两次就可以了,因为只用到了第i,和第i-1;所以修改代码
第二版:
import java.util.Scanner;
public class Main {
/**
* 有N件物品,有一个体积为V的背包
* 第i件物品的费用为c[i],价值是w[i];
* 问:如何价值最大
* <p>
* <p>
* <p>
4 6
1 4
2 6
3 12
2 7
*/
public static int getMaxWorth(int N, int V, int[] c, int[] v) {
x=new int[V+1];
f = new int[V + 1];
int maxWorth = 0;
//如果不输入,默认就为0
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= V; j++) {
if (j >= c[i - 1]) {
f[j] = x[j] > x[j - c[i - 1]] + v[i - 1] ? x[j] : x[j - c[i - 1]] + v[i - 1];
}
// System.out.println("放"+i+"件物品,当背包体积为"+j+"时,价值为:"+f[j]);
}
copy(f,x);
if (maxWorth < f[V]) {
maxWorth = f[V];
}
}
return maxWorth;
}
public static void copy(int[] f,int[]x){
for (int i = 0; i < f.length; i++) {
x[i]=f[i];
}
}
//N为物品个数
// V为体积大小
static int N, V;
static int[] c, v;
static int[] f,x;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//依次输入物品个数和体积大小
N = scanner.nextInt();
V = scanner.nextInt();
c = new int[N];
v = new int[N];
//输入物品详情
for (int i = 0; i < N; i++) {
c[i] = scanner.nextInt();
v[i] = scanner.nextInt();
}
System.out.println(getMaxWorth(N, V, c, v));
}
}
此时就可以Accept了,所以在创建数组一定不能过大,或者说每个数组都要有其作用。不用就要将其释放。
第三版:
单数组倒叙版:
public class Main {
/**
* 有N件物品,有一个体积为V的背包
* 第i件物品的费用为c[i],价值是w[i];
* 问:如何价值最大
* <p>
* <p>
* <p>
4 6
1 4
2 6
3 12
2 7
*/
public static int getMaxWorth(int N, int V, int[] c, int[] v) {
int[] f=new int[V+1];
int maxWorth = 0;
//如果不输入,默认就为0
for (int i = 1; i <= N; i++) {
for (int j = V; j>=c[i-1]; j--) {
f[j] = Math.max(f[j],f[j - c[i - 1]]+v[i-1]);
// System.out.println("放"+i+"件物品,当背包体积为"+j+"时,价值为:"+f[j]);
}
if (maxWorth < f[V]) {
maxWorth = f[V];
}
}
return maxWorth;
}
public static void copy(int[] f,int[]x){
for (int i = 0; i < f.length; i++) {
x[i]=f[i];
}
}
//N为物品个数
// V为体积大小
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//依次输入物品个数和体积大小
int N = scanner.nextInt();
int V = scanner.nextInt();
int[] c = new int[N];
int[] v = new int[N];
//输入物品详情
for (int i = 0; i < N; i++) {
c[i] = scanner.nextInt();
v[i] = scanner.nextInt();
}
System.out.println(getMaxWorth(N, V, c, v));
}
}
第四版:和第三版相同
对于数组名称进行整理
import java.util.Scanner;
public class Main {
/**
* 有N件物品,有一个体积为V的背包
* 第i件物品的费用为c[i],价值是w[i];
* 问:如何价值最大
* <p>
* <p>
* <p>
4 6
1 4
2 6
3 12
2 7
*/
public static int getMaxWorth(int N, int V, int[] c, int[] v) {
int[] f=new int[V+1];
int maxWorth = 0;
//如果不输入,默认就为0
for (int i = 1; i <= N; i++) {
for (int j = V; j>=c[i]; j--) {
f[j] = Math.max(f[j],f[j - c[i]]+v[i]);
// System.out.println("放"+i+"件物品,当背包体积为"+j+"时,价值为:"+f[j]);
}
if (maxWorth < f[V]) {
maxWorth = f[V];
}
}
return maxWorth;
}
//N为物品个数
// V为体积大小
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//依次输入物品个数和体积大小
int N = scanner.nextInt();
int V = scanner.nextInt();
int[] n = new int[N+1];
int[] v = new int[N+1];
//输入物品详情
for (int i = 1; i <=N; i++) {
n[i] = scanner.nextInt();
v[i] = scanner.nextInt();
}
System.out.println(getMaxWorth(N, V, n, v));
}
}
背包问题大神
dd_engi 的背包九讲:http://blog.youkuaiyun.com/u011439362/article/details/9612127
写在最后
数组使用注意释放,或者在其创建就需要注意内存溢出问题。
本文通过四个版本的代码展示了如何逐步优化解决背包问题的过程,从最初的双数组到单数组倒叙优化,有效避免了内存溢出问题。
2277

被折叠的 条评论
为什么被折叠?



