### 解题

dp[i][v-w[i]] 可能不好理解，举个例子，当前体积是5，第二个物品占用的体积是2，装第二个物品时，前俩个物品恰好装满体积3时，在放入一个第二个物品也是可以装满体积5的。

``````
public class Main {
static int[][] dp = new int[5000][5000];

public static void main(String[] args) throws Exception {
//int[] num = {0, 1, 2, 3, 4, 5};
int[] num = {0,  2, 3, 4, 5};
int total = 5;
init();

for (int v = 1; v <= total; ++v) {
for (int i = 1; i < num.length; ++i) {
if (v < num[i]) {
dp[i][v] = dp[i - 1][v];
continue;
}
dp[i][v] = dp[i - 1][v] + dp[i][v - num[i]];
}
}
System.out.println(dp[num.length - 1][total]);
}

private static void init() {
for (int i = 0; i < 5000; i++) {
dp[i][0] = 1;
}
}
}
``````

### dp数组二维降成一维

dp[v] = dp[v] + dp[v-num[i]]

``````/**
* Created by Yanwu 2018/2/8.
*/
public class Main {

//static int[] dp2 = new int[5000];
static int[] num = {0, 1, 2, 4};
static int total = 5;
static int[] dp2 = new int[total + 1];
static int[][] dp = new int[total + 1][total + 1];

public static void main(String[] args) throws Exception {
//int[] num = {0, 1, 2, 3, 4, 5};
dp1();
dp2();
}

private static void dp1() {

init();
for (int v = 1; v <= total; ++v) {
for (int i = 1; i < num.length; ++i) {
if (v < num[i]) {
dp[i][v] = dp[i - 1][v];
continue;
}
dp[i][v] = dp[i - 1][v] + dp[i][v - num[i]];
}
}
System.out.println(dp[num.length - 1][total]);
}

private static void dp2() {
dp2init();

int total = 5;

for (int i = 1; i < num.length; ++i) {
for (int v = 1; v <= total; ++v) {
if (v - num[i] >= 0) {
dp2[v] = dp2[v] + dp2[v - num[i]];
}

}
}
System.out.println(dp2[total]);
}

private static void dp2init() {
for (int i = 0; i < dp2.length; ++i) {
dp2[i] = 0;
}
dp2[0] = 1;

}

private static void init() {
for (int i = 0; i <= total; i++) {
dp[i][0] = 1;
}
}
}
``````