题目
描述
给定 n 个不同的正整数,整数 k(k \leq n)(k≤n)以及一个目标数字 target。
在这 n 个数里面找出 k 个数,使得这 k 个数的和等于目标数字,求问有多少种方案?
样例
样例 1:
输入:
A = [1,2,3,4]
k = 2
target = 5
输出:
2
解释:
1 + 4 = 2 + 3 = 5
样例 2:
输入:
A = [1,2,3,4,5]
k = 3
target = 6
输出:
1
解释:
只有这一种方案。 1 + 2 + 3 = 6
分析
解读题意,给定一个数组A,两个变量k和target,要求从数组A中拿出k个数字他们之和为target,求有多少种方案,每个数字只能拿一次。
判断是一道01背包型动态规划的题,但是多了一个限制条件k,如果没有k的情况下,我们直接就创建一个二维数组,一个代表当前的物品,一个代表背包的最大承重,这里只需要把k加入到状态中即可,还是老方法,先分析最后一步,然后分析转移方程。
1.最后一步
最后一个物品拿还是不拿
情况一不拿
如果最后一个物品不拿,当前方案数最大就是前n-1个物品选k个的最大方案数
情况二拿
最大方案数就是就是前n-1个物品选k-1个的最大方案数
注意选当前物品时背包的最大承重要大于当前的物品(就是说背包可以装的下当前的物品)
2.转移方程
状态f[i][j][k],意思是前i个物品中选前j个,总重量达到k的最大方案数
不拿当前物品时f[i][j][k]=f[i-1][j][k]
拿当前物品时f[i][j][k]=f[i-1][j-1][k-A[i-1]]
拿或者不拿是两个相对的状态,所以总的状态应该将这两种状态加起来
f[i][j][k]=f[i-1][j][k]+f[i-1][j-1][k-A[i-1]]|(j-1>=0&&k>=A[i-1])
代码部分
1.初始化
状态需要0的情况,就是在前0个数字中选…
int len=A.size();
//前len个数字中选k个和为target,方案数量最多
vector<vector<vector<int> > > f(len+1,
vector<vector<int> >(k+1,vector<int>(target+1)));
转移方程中,我们需要上一行的数据,所以正常来说我们应该初始化第一行
初始化f[0][0][0],在前0个数字中选0个使总重量为0,这种情况我们什么都不用做就满足,所以这种情况下我们应该初始化为1
当前0个数字的情况,不论是拿1个2个,还是想使总重量达到几,都是达不到的,所以我们应该初始化f[0][0j][0k]的所有值为0
f[0][0