给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。 当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。
输入描述:
输入为两行:
第一行为两个正整数n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000)
第二行为n个正整数A[i](32位整数),以空格隔开。
输出描述:
输出所求的方案数
输入例子:
5 15
5 5 10 2 3
输出例子:
4
思路:暴力搜索O(2^1000)时间复杂度较大不行,运用dp求解;
dp[i][j]:=用前i种数字合成j的方案数;
则,为了使前i种数字和成j,也就需要能用前i-1种数字加和成j或j-a[i];
dp[i][j]=dp[i-1][j]+dp[i-1][j-a[i]];(j>=a[i])
dp[i][j]=dp[i-1][j];(j<a[i])
---------------------
作者:H煊
来源:CSDN
原文:https://blog.csdn.net/m0_37846371/article/details/72718142
版权声明:本文为博主原创文章,转载请附上博文链接!
暴力枚举
import java.util.*;
public class Coin4dfs {
public static int cnt=0;
public static void main(String args[]){
Scanner in=new Scanner(System.in);
while(in.hasNext()){
int n=in.nextInt();
int total=in.nextInt();
int arr[]=new int[n];
for(int i=0;i<n;i++){
arr[i]=in.nextInt();
}
dfs(0,0,arr,total);
System.out.println(cnt);
}
}
public static void dfs(int sum,int pos,int arr[],int total){
if(sum>total)
return;
else if(sum==total){
cnt++;
return ;
}else{
for(int i=pos;i<arr.length;i++){ //sum要记得更新回来,sum+=arr[i],还要有sum-=arr[i]
sum+=arr[i];
dfs(sum,i+1,arr,total);
sum-=arr[i];
}
}
}
}
01背包-动态规划
import java.util.*;
public class Coin4 {
public static void main(String args[]){
Scanner in=new Scanner(System.in);
while(in.hasNext()) {
int n = in.nextInt();
int arr[] = new int[n];
int sum = in.nextInt();
for (int i = 0; i < n; i++) {
arr[i] = in.nextInt();
}
//注意边界条件的初始化
int dp[][]=new int[n+1][sum+1];
for(int j=1;j<=sum;j++)
dp[0][j]=0;
dp[0][0]=1;
//注意更新策略
for(int i=1;i<=arr.length;i++){
for(int j=0;j<=sum;j++){
if(j<arr[i-1]){
dp[i][j]=dp[i-1][j];
}else{
dp[i][j]=dp[i-1][j]+dp[i-1][j-arr[i-1]];
}
}
}
System.out.println(dp[arr.length][sum]);
}
}
}