数字和为sum的方法数

数字和为sum的方法数

1.题目描述

给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。
输入描述:
输入为两行:
第一行为两个正整数n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000)
第二行为n个正整数A[i] ( 32位整数),以空格隔开。
输出描述:
输出所求的方案数

示例1
在这里插入图片描述

2.思路(动态规划)

(1)递推关系为:dp[i][j] = dp[i-1][j] + dp[i-1][j-A[i]]
  dp[i-1][j]:表示不用第i个数字能凑到j的最多情况
  dp[i-1][j-value[i]]:用了i时,原来凑到j-value[i]的最多情况
(2)两个相加dp[i][j]代表用前i个数字凑到j最多有多少种方案。
  其中i表示数组下标,j表示和为j,由于递推关系dp[i][j]只与i-1有关,因此空间复杂度可以优化为O(n),即dp[j] = dp[j] + dp[j-A[i]],表示组合成j的方法总数等于取到当前数子A[i]时组合成j-A[i]的方法总数加上没有取到当前数字A[i]时的方法总数。
(3)dp[0]=1; //初始化,表示凑到0永远有1种方案(什么数都不取)。

3.代码

#include <iostream>
#include <vector>
using namespace std;
int main(){
    int n = 0, sum = 0;
    cin >> n >> sum;
    vector<int> nums(n);
    vector<long> dp(sum+1);
    for(int i = 0;i < n;++i){
        cin >> nums[i];
    }
    dp[0] = 1;//组合成0有一种方法,即取0个数
    for(int i = 0;i < n;++i){
        for(int j = sum;j >= nums[i];--j){
            dp[j] += dp[j-nums[i]];
        }
    }
    cout << dp[sum] << endl;
    return 0;
}

4.复杂度分析

时间复杂度:O(n^2)
空间复杂度:O(n)

发布了196 篇原创文章 · 获赞 0 · 访问量 5520

猜你喜欢

转载自blog.csdn.net/jiangdongxiaobawang/article/details/104440973
今日推荐