数字和为sum的方案数

数字和为sum的方法数

给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。 
当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。 输入 
5 15

5 5 10 2 3 
输出 
4

import java.util.Scanner;

public class KK {
	public static void main(String[] args) {
		// 动态规划求解如下:
		/*5 15 
		 *5 5 10 2 3 
		 *4
		 * sum值是指定的,但是解空间肯定是最小单位为1进行增长, 所以想到dp[i][j]表示前缀为 i ,
		 * 能组成值为 j 的可能性个数。
		 * 然后行序求解,如果这个p[i] <= j ,说明有组成 j 的可能,
		 *  p[i] > j ,则dp[i][j] 就是不考虑 p[i]的前 i - 1 个数组成 j 。
		 * 			
		 * 				dp[i-1][j]+	dp[i-1][j- p[i]]	(p[i] <= j)		
		 *  dp[i][j] = 
		 *  			dp[i-1][j]						 (p[i] > j)   
		 * 
		 */
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[] p = new int[n + 1];
		long[][] dp = new long[n + 1][m + 1];// dp[i,j]表示前i个可以凑到j的个数
		for (int i = 1; i <= n; i++) {
			p[i] = sc.nextInt();
		}
		// 用前i个数据组成0的方案只有一种
		for (int i = 0; i <= n; i++) {
			dp[i][0] = 1;
		}
		// 用前0个数据组成j的方案不存在
		for (int j = 1; j <= m; j++) {
			dp[0][j] = 0;
		}
		for (int i = 1; i <= n; i++) {
			for (int j = 0; j <= m; j++) {
				// 等于拿了这个数据和没拿这个数据的方案总和,
				//没拿时只需要看前i-1个数据组成j-p[i]的方案数
				if (p[i] <= j) {
					dp[i][j] = dp[i - 1][j] + dp[i - 1][j - p[i]];
				} else {// p[i]>j时只能选择不拿
					dp[i][j] = dp[i - 1][j];
				}
			}
		}
		System.out.println(dp[n][m]);
		for (int i = 0; i < dp.length; i++) {
			for (int j = 0; j < dp[i].length; j++) {
				System.out.print(dp[i][j]+" ");
			}
			System.out.println();
		}
		 
	}
}

 

你可能感兴趣的:(leetcode)