Target Sum
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);
}
}
}