Target Sum
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
There is a sequence of N positive integers A1, A2, ... AN and a target sum S. You need to add a plus or minus operator (+/-) before every integer so that the resulted expression equals to S. Find out the number of such expressions.
Example if the sequence A is [1, 1, 1, 1, 1] and the target sum S is 3. There are 5 valid expressions: -1+1+1+1+1=3, +1-1+1+1+1=3, +1+1-1+1+1=3, +1+1+1-1+1=3 and +1+1+1+1-1=3.
输入
The first line contains 2 integers N and S denoting the number of integers and the target sum.
The second line contains N integers A1, A2, ... AN.
For 80% of the data: 1 <= N <= 10
For 100% of the data: 1 <= N <= 100 1 <= S <= 100000 1 <= Ai <= 1000
输出
The number of valid expressions. The answer may be very large so you only need to output the answer modulo 1000000007.
样例输入
5 3
1 1 1 1 1
样例输出
5
首先每个数的大小是[1, 1000]
,所以所有数的和的范围是[-100000, 100000]
。
我们可以用f[i][j]
表示前i
个数中,和是(j-100000)
一共有几种方法。
这里(j-100000)
主要是考虑到数组下标不能是负数。
初始值是f[0][100000] = 1
递推方程大概是f[i][j] = f[i-1][j-A[j]] + f[i-1][j+A[j]]
,需要考虑一下j-A[j]
和j+A[j]
的范围。
由于f[i][]
的值全部是由f[i-1][]
计算得来,所以可以用滚动数组优化空间复杂度。
整体的时间复杂度是O(NR)
其中R
是和的取值范围。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int S = scanner.nextInt();
int[] a = new int[N];
for (int i = 0; i < N; i++) {
a[i] = scanner.nextInt();
}
System.out.println(solve(N, S, a));
scanner.close();
}
private static int solve(int N, int S, int[] a) {
final int M = 1000000007;
int maxSum = 0;
for (int i = 0; i < N; i++) {
maxSum += Math.abs(a[i]);
}
int compensate = maxSum + 1000;
int[][] dp = new int[N + 1][2 * compensate + 1];
dp[1][a[0] + compensate] = 1;
dp[1][-a[0] + compensate] = 1;
for (int i = 2; i < N + 1; i++) {
for (int j = 1000; j <= 2 * maxSum + 1000; j++) {
dp[i][j] = (dp[i - 1][j - a[i - 1]] + dp[i - 1][j + a[i - 1]]) % M;
}
}
return dp[N][S + compensate];
}
}
dfs
import java.util.Scanner;
public class Main {
static int count = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int targetSum = sc.nextInt();
int[] numbers = new int[n];
for (int index = 0; index < n; index++) {
int number = sc.nextInt();
numbers[index] = number;
}
countMatchSum(1, numbers, targetSum - numbers[0]);
countMatchSum(1, numbers, targetSum + numbers[0]);
System.out.println(count);
}
public static void countMatchSum(int index, int[] numbers, int targetSum) {
int number = numbers[index++];
if (numbers.length == index && (number == targetSum || -number == targetSum)) {
count++;
}
if (numbers.length > index) {
countMatchSum(index, numbers, targetSum - number);
countMatchSum(index, numbers, targetSum + number);
}
}
}