描述
给定 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加入到状态中即可,还是老方法,先分析最后一步,然后分析转移方程。
最后一个物品拿还是不拿
情况一不拿
如果最后一个物品不拿,当前方案数最大就是前n-1个物品选k个的最大方案数
情况二拿
最大方案数就是就是前n-1个物品选k-1个的最大方案数
注意选当前物品时背包的最大承重要大于当前的物品(就是说背包可以装的下当前的物品)
状态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])
状态需要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][0]=1;
//初始化前0个物品的情况
for(int i=0;i<=k;i++)
for(int j=0;j<=target;j++)
{
if(i!=0||j!=0)
f[0][i][j]=0;
}
按顺序计算[1][0][0]…[1][0][k]…[1][j][k]
[i][0][0]…[i][0][k]…[i][j][k]
最后结果就是f[i][j][k]
要注意对下标进行判断,考虑所有可能出现的数组越界访问情况
for(int i=1;i<=len;i++) //动规核心
{
for(int j=0;j<=k;j++)
{
for(int l=0;l<=target;l++)
{
f[i][j][l]=f[i-1][j][l];
if(l>=A[i-1]&&j-1>=0)
f[i][j][l]+=f[i-1][j-1][l-A[i-1]];
}
}
}
class Solution {
public:
//选最后一个物品:f[i-1][k-1][target-A[i-1]]
//不选最后一个物品:f[i-1][k][target]
int kSum(vector<int> &A, int k, int target) {
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]=1;
//初始化前0个物品的情况
for(int i=0;i<=k;i++)
for(int j=0;j<=target;j++)
{
if(i!=0||j!=0)
f[0][i][j]=0;
}
for(int i=1;i<=len;i++) //动规核心
{
for(int j=0;j<=k;j++)
{
for(int l=0;l<=target;l++)
{
f[i][j][l]=f[i-1][j][l];
if(l>=A[i-1]&&j-1>=0)
f[i][j][l]+=f[i-1][j-1][l-A[i-1]];
}
}
}
return f[len][k][target];
}
};
01背包问题,多了一个限制的条件,其他不变,我们还是按照正常的思路分析最后一步,然后分析转移方程,唯一不同的是,需要把这个变量代入到我们的状态中。