1. 程式人生 > >Target Sum

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

}