注:大佬对此类问题的解法:动态规划背包问题总结
给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。
题目数据保证答案符合 32 位整数范围。
示例 1:
输入:nums = [1,2,3], target = 4
输出:7
解释:
所有可能的组合为:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
请注意,顺序不同的序列被视作不同的组合。
示例 2:
输入:nums = [9], target = 3
输出:0
提示:
1 <= nums.length <= 200
1 <= nums[i] <= 1000
nums 中的所有元素 互不相同
1 <= target <= 1000
#include
// 定义一个函数来计算总和为目标整数的元素组合的个数
int combinationSum4(int* nums, int numsSize, int target) {
// 创建一个动态规划数组 dp,长度为 target + 1
int dp[target + 1];
// 初始化 dp 数组,将所有元素初始化为0
for (int i = 0; i <= target; i++) {
dp[i] = 0;
}
// 初始状态:总和为0时,只有一种组合方式,即什么都不选
dp[0] = 1;
// 开始填充 dp 数组
for (int i = 1; i <= target; i++) {
for (int j = 0; j < numsSize; j++) {
// 如果当前的目标总和减去数组元素可达
if (i - nums[j] >= 0) {
// 则将 dp[i] 增加 dp[i - nums[j]],表示加上当前元素后的组合数
dp[i] += dp[i - nums[j]];
}
}
}
// 返回 dp 数组中最终目标总和的组合数
return dp[target];
}
int main() {
int nums[] = {1, 2, 3};
int target = 4;
int numsSize = sizeof(nums) / sizeof(nums[0]);
// 调用 combinationSum4 函数,计算组合数
int result = combinationSum4(nums, numsSize, target);
// 打印结果
printf("输出:%d\n", result);
return 0;
}
在动态规划中,dp[i - nums[j]] 表示以目标值 i 减去数组中的某个元素 nums[j] 后的状态。这通常用于动态规划问题中,特别是在处理组合问题时,来记录前一步的状态。
在上述程序中,dp[i] 表示总和为 i 的组合数。当计算 dp[i] 时,我们遍历数组 nums 中的元素,对于每个元素 nums[j],我们考虑将其加入总和为 i 的组合中。为了计算 dp[i],我们需要考虑两种情况:
所以,dp[i - nums[j]] 表示以目标值 i 减去数组中的某个元素 nums[j] 后的状态,即剩余的部分。通过考虑所有可能的 nums[j],我们可以累加所有这些情况,以计算总和为 i 的组合数 dp[i]。这就是动态规划的思想:将较大问题分解成较小问题,并使用较小问题的解来构建较大问题的解。
假设数组 nums 为 [1, 2, 3],目标值 target 为 4。
初始时,dp 数组如下:
dp[0] = 1
dp[1] = 0
dp[2] = 0
dp[3] = 0
dp[4] = 0
开始计算 dp[1]:
最终,dp[4] 的值为 3,表示总和为 4 的组合数为 3 种,即 [1, 1, 1, 1]、[1, 1, 2] 和 [2, 2]。