动态规划几部曲
简单记述下动态规划的步骤与注意事项
- dp数组的的含义
- 数组初始化
- 状态转移方程
经典求最少/多组合数:dp[j] = min(dp[j-nums[i]]+1, dp[j]);
求能够凑成的组合数:dp[j] += dp[j-nums[i]]; - 完全背包还是01背包
完全背包可以无限使用物品,遍历时从前往后推,如零钱兑换
01背包一个物品只能用一次,遍历时从后往前推,如目标和for(int i=0; i<coins.size(); ++i){ for(int j=1; j<=amount; ++j){ if(j>=coins[i] && dp[j-coins[i]] != INT_MAX) dp[j] = min(dp[j], dp[j-coins[i]]+1); } }
for (int i = 0; i < nums.size(); i++) { for (int j = bagSize; j >= nums[i]; j--) { dp[j] += dp[j - nums[i]]; } }
- 确定遍历的顺序
组合不强调顺序,(1,6),(6,1)属于同一个组合
排列强调顺序,1,6),(6,1)属于不同排列
如果求组合数就是外层for循环遍历物品,内层for遍历背包
如果求排列数就是外层for遍历背包, 内层for循环遍历物品