java算法背包放物品最大_每天一道算法题(四) (动态规划算法)01背包问题Java实现...

动态规划

动态规划在wiki上的定义:

dynamic programming is a method for solving a complex problem by breaking it down into a collection of simpler subproblems, solving each of those subproblems just once, and storing their solutions - ideally, using a memory-based data structure. The next time the same subproblem occurs, instead of recomputing its solution, one simply looks up the previously computed solution。

昨天接触到了动态规划的概念,研究了昨天一晚上以及今天一上午,总算对这个问题有些收获。

动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再合并子问题的解以得出原问题的解。

从空集合开始,每增加一个元素就求它的最优解,直到所有元素加进来,就得到了总的最优解。

01背包问题

01背包问题即的01即每件物品最多放1件,否则不放入。

让我真正了解动态规划概念的是mu399的博客

问题:有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?

重新定义问题:

有承重分别为1-10的背包10个

编号分别为a,b,c,d,e的物品各一个

name

weight

value

a

2

6

b

2

3

c

6

5

d

5

4

e

4

6

3. 从e物品开始依次放入1-10个背包,分别得到最大的价值总和

4. 把d物品放入依次放入存在e物品的1-10个背包,如果价值更高,替换掉e()

5. c,b,a同理。。。

name

weight

value

1

2

3

4

5

6

7

8

9

10

e

4

6

0

0

0

6

6

6

6

6

6

6

d

5

4

0

0

0

6

6

6

6

6

10

10

c

6

5

0

0

0

6

6

6

6

6

10

11

b

2

3

0

3

3

6

6

9

9

9

10

11

a

2

6

0

6

6

9

9

12

12

15

15

15

思路:

1. 01背包的状态转换方程 f[i,j] = Max{f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] }

f[i,j]:在前i件物品中选择若干件放在承重为 j 的背包中,可以取得的最大价值。

Pi表示第i件物品的价值。

决策:为了背包中物品总价值最大化,第 i件物品应该放入背包中吗 ?

2. 以a8(行为a,列为的8的单元格)举例

f[i,j] = a8 = 15

f[i-1,j] = b8 = 9

f[i-1,j-Wi] 表示我有一个承重为6的背包(等于当前背包承重减去物品a的重量),当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值

f[i-1,j-Wi] +Pi =b(8 - 2) + 6 = b6 + 6 = 15

背包的java代码实现

public class getPgAnswer{

@Test

public void testPackage() {

Package[] pg = {new Package("e",4,6),

new Package("d",5,4),

new Package("c",6,5),

new Package("b",2,3),

new Package("a",2,6)

};

// 第一个参数表示从pg[0]开始依次放入的物品,

// 第二个参数代表背包的承重,放弃第0列数组

int[][] state = new int[pg.length][11];

int newValue = 0;

/** * 01背包的状态转换方程 * f[i,j] = Max{ * f[i-1,j-Wi]+Pi( j >= Wi ), * f[i-1,j] } */

for (int i = 0; i < pg.length; i++) {

// 背包的承重量

for (int j = 1; j < state[i].length; j++) {

if (i == 0) {

if (pg[i].getWeight() <= j) {

state[i][j] = pg[i].getValue();

}

}else{

state[i][j] = state[i - 1][j];

if (j < pg[i].getWeight()) {

continue;

}

newValue = state[i - 1][j - pg[i].getWeight()]

+ pg[i].getValue();

/* if (newValue >= state[i - 1][j]) { state[i][j] = newValue; }else{ state[i][j] = state[i - 1][j]; }*/

state[i][j] = Math.max(newValue, state[i - 1][j]);

}

}

}

for (int i = 0; i < state.length; i++) {

System.out.println(Arrays.toString(state[state.length - 1 - i]));

}

}

}

class Package {

private String name;

private int weight;

private int value;

public Package(String name,int weight,int value){

this.name = name;

this.weight = weight;

this.value = value;

}

public String getName() {

return name;

}

public int getWeight() {

return weight;

}

public int getValue() {

return value;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值