题目描述:
给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。
当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。
输入描述:
输入为两行:
第一行为两个正整数n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000)
第二行为n个正整数A[i],以空格隔开。
输出描述:
输出所求的方案数
例子:
输入
5 15 5 5 10 2 3
输出
4
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int sum = sc.nextInt();
int[] arr = new int[n + 1];
for (int i = 1; i <= n; i++) {
arr[i] = sc.nextInt();
}
//dp[i][j]二维表中每个元素表示前i个数字中和为j的方案数
int[][] dp = new int[n + 1][sum + 1];
//当 j = 0 时,前i个数字和为0的方案数都为1
for (int i = 0; i <= n; i++) {
dp[i][0] = 1;
}
//当 i = 0 时,前0个数字和为 j(j != 0) 的方案数为0
for (int j = 1; j <= sum; j++) {
dp[0][j] = 0;
}
//接下来只要填表就行
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= sum; j++) {
/*
对于 dp[i][j] 这里分两种情况:
1.第 i 个数大于 j,说明第i个数不可能包含在任意的方案中
这里很好理解,因为如果第 i 个数在一个方案中,那么这个方案的数字和
肯定大于 j, 所以前 i 个数之和为 j 的方案数就等于前 i - 1 个数之和
为 j 的的方案数,即 dp[i][j] == dp[i - 1][j]
2.第 i 个数小于等于 j,此时所有的方案可以分成两部分
a)把第 i 个数不加入到方案:
则此时和为 j 共有 dp[i - 1][j] 种方案
b) 把第 i 个数加入到方案:
此时要求的和为 j 已经满足了 arr[i],只要在前 i - 1 个数中找到
和为 j - arr[i] 的方案数即可,即 dp[i - 1][j - arr[i]]
因此情况2共有 dp[i - 1][j] + dp[i - 1][j - arr[i]] 种方案
*/
if (arr[i] <= j) {
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - arr[i]];
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
System.out.println(dp[n][sum]);
}
}
}