LintCode 564: Combination SumIV (DP 經典題)
阿新 • • 發佈:2018-12-16
這題類似完全揹包。 程式碼如下:
class Solution { public: /** * @param nums: an integer array and all positive numbers, no duplicates * @param target: An integer * @return: An integer */ int backPackVI(vector<int> &nums, int target) { int n = nums.size(); vector<int> dp(target + 1, 0); //dp[i] is the number of possible combinations that add up to i dp[0] = 1; for (int j = 0; j <= target; ++j) { for (int i = 0; i < n; ++i) { if (j >= nums[i]) dp[j] += dp[j - nums[i]]; // cout<<"i="<<i<<" j="<<j<<" dp="<<dp[j]<<endl; } } return dp[target]; } };
注意: 1)迴圈i和迴圈j不能互換(即不能先i迴圈,再j迴圈)。否則出錯。 以nums=[1,2,4]和target=4為例, 上面的列印資訊為: i=0 j=0 dp=1 i=1 j=0 dp=1 i=2 j=0 dp=1 i=0 j=1 dp=1 i=1 j=1 dp=1 i=2 j=1 dp=1 i=0 j=2 dp=1 i=1 j=2 dp=2 i=2 j=2 dp=2 i=0 j=3 dp=2 i=1 j=3 dp=3 i=2 j=3 dp=3 i=0 j=4 dp=3 i=1 j=4 dp=5 i=2 j=4 dp=6
但如果我們把迴圈i和迴圈j的順序倒過來,即
for (int i = 0; i < n; ++i) { for (int j = nums[i]; j <= target; ++j) { dp[j] += dp[j - nums[i]]; //cout<<"i = "<<i<<" j="<<j<<" dp="<<dp[j]<<endl; } }
則列印資訊為: i=0 j=1 dp=1 i=0 j=2 dp=1 i=0 j=3 dp=1 i=0 j=4 dp=1 i=1 j=2 dp=2 i=1 j=3 dp=2 i=1 j=4 dp=3 i=2 j=4 dp=4