# 完全背包的排列问题模拟 #### Problem 1. 排列问题是完全背包中十分棘手的问题。 2. 其在迭代过程中需要先迭代背包容量,再迭代物品个数,使得其在代码理解上较难入手。 #### Contribution 本文档以力扣上[组合总和IV](https://leetcode.cn/problems/combination-sum-iv/)为例,提供一个二维dp的代码例子,并提供模拟过程以便于理解 #### Code ```cpp int combinationSum4(vector& nums, int target) { // 定义背包容量为target,物品个数为nums.size()的dp数组 // dp[i][j]表示将第0-i个物品添加入排列中,和为j的排列方式 vector> dp (nums.size(), vector(target+1,0)); // 表示有0,1,...,n个物品可选择的情况下,和为0的选择方法为1:什么都不取 for(int i = 0; i < nums.size(); i++) dp[i][0] = 1; // 必须按列遍历,因为右边数组需要知道左边数组最低部的信息(排列问题) // 后面的模拟可以更清楚的表现这么操作的原因 for(int i = 1; i <= target; i++){ for(int j = 0; j < nums.size(); j++){ // 只有nums[j]可以取的情况 if(j == 0){ if(nums[j] > i) dp[j][i] = 0; // 如果背包容量放不下 那么此时没有排列方式 else dp[j][i] = dp[nums.size()-1][i-nums[j]]; // 如果背包容量放的下 全排列方式为dp[最底层][容量-该物品容量]排列方式后面放一个nums[j] } // 有多个nums数可以取 else{ // 如果背包容量放不下 那么沿用0-j-1个物品的排列方式 if(nums[j] > i) dp[j][i] = dp[j-1][i]; // 如果背包容量放得下 在dp[最底层][容量-该物品容量]排列方式后面放一个nums[j]后面放个nums[j] // INT_MAX避免溢出 else if(i >= nums[j] && dp[j-1][i] < INT_MAX - dp[nums.size()-1][i-nums[j]]) dp[j][i] = dp[j-1][i] + dp[nums.size()-1][i-nums[j]]; } } } // 打印dp数组 for(int i = 0; i < nums.size(); i++){ for(int j = 0; j <= target; j++){ cout<