给定一个数组,求数组里面的值的和为某个值的方案总数(动态规划)

题目链接

牛客网:数字和为sum的方法数

题意

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

思路

动态规划,设dp[n][m]是前n个数,和为m的总的方案数
那么如果第n个数不选,那么dp[n][m]=dp[n-1][m]
如果选择第n个数,那么dp[n][m]=dp[n-1][m-A[n]]
所以总的方案数为dp[n][m]=dp[n-1][m]+dp[n-1][m-A[n]]

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
long long dp[1010][1010];
long long a[1010];
int main(int argc, char** argv)
{
//    freopen("in.txt", "r", stdin);
    int n,sum;
    scanf("%d %d",&n,&sum);//dp[n][m] 用n个数 求和得到sum的方案总数 
    for(int i=1;i<=n;i++) {
    	scanf("%d",&a[i]);
	}
	//边界条件 dp[i][0]=1;
	for(int i=0;i<=n;i++){
		dp[i][0]=1;
	} 
	
	for(int i=1;i<=n;i++){
		for(int j=0;j<=sum;j++){
//			if(j>=a[i]) dp[i][j]+=dp[i-1][j-a[i]];//第i个数选或者不选
			if(j>=a[i]) 
				dp[i][j]=dp[i-1][j]+dp[i-1][j-a[i]];//不选a[i] + 选了a[i]的方案总数
			 else
			 	dp[i][j]=dp[i-1][j];//一定不能选 
		}
	}
//	dp[1][a[1]]=1;
//	
//	for(int i=2;i<=n;i++){
//		for(int j=1;j<i;j++){
//			
//			for(int k=sum;k>=a[j];k--){
//				dp[i][k]+=dp[j][k-a[j]];
//			}
//		}
//	}
//	
	printf("%lld\n",dp[n][sum]);
    return 0;
}

posted @ 2020-11-20 11:16  xzhws  阅读(681)  评论(0编辑  收藏  举报