<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>knapsack Archives - Huahua&#039;s Tech Road</title>
	<atom:link href="https://zxi.mytechroad.com/blog/tag/knapsack/feed/" rel="self" type="application/rss+xml" />
	<link>https://zxi.mytechroad.com/blog/tag/knapsack/</link>
	<description></description>
	<lastBuildDate>Wed, 14 Nov 2018 02:42:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.0.8</generator>

<image>
	<url>https://zxi.mytechroad.com/blog/wp-content/uploads/2017/09/cropped-photo-32x32.jpg</url>
	<title>knapsack Archives - Huahua&#039;s Tech Road</title>
	<link>https://zxi.mytechroad.com/blog/tag/knapsack/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Knapsack Problem 背包问题</title>
		<link>https://zxi.mytechroad.com/blog/sp/knapsack-problem/</link>
					<comments>https://zxi.mytechroad.com/blog/sp/knapsack-problem/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 10 Nov 2018 17:37:14 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[SP]]></category>
		<category><![CDATA[combination]]></category>
		<category><![CDATA[DFS]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[knapsack]]></category>
		<category><![CDATA[optimization]]></category>
		<guid isPermaLink="false">https://zxi.mytechroad.com/blog/?p=4270</guid>

					<description><![CDATA[<p>Videos 上期节目中我们对动态规划做了一个总结，这期节目我们来聊聊背包问题。 背包问题是一个NP-complete的组合优化问题，Search的方法需要O(2^N)时间才能获得最优解。而使用动态规划，我们可以在伪多项式（pseudo-polynomial time）时间内获得最优解。 0-1 Knapsack Problem 0-1背包问题 Problem Given N items, w[i] is the weight of the i-th item and v[i] is value of&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/knapsack-problem/">Knapsack Problem 背包问题</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Videos</h1>
<p><iframe width="500" height="375" src="https://www.youtube.com/embed/CO0r6kcwHUU?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<p><iframe width="500" height="375" src="https://www.youtube.com/embed/rM_G4dboKhc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<h1></h1>
<p>上期节目中我们对动态规划做了一个总结，这期节目我们来聊聊背包问题。</p>
<p>背包问题是一个NP-complete的组合优化问题，Search的方法需要O(2^N)时间才能获得最优解。而使用动态规划，我们可以在<strong>伪多项式（pseudo-polynomial time）</strong>时间内获得最优解。</p>
<h1><strong>0-1 Knapsack Problem 0-1背包问题</strong></h1>
<h2>Problem</h2>
<p><span style="font-weight: 400;">Given N items, w[i] is the weight of the i-th item and v[i] is value of the i-th item. Given a knapsack with capacity W. Maximize the total value. Each item can be use </span><span style="color: #ff0000;"><b>0 or 1 time</b></span><span style="font-weight: 400;">.</span></p>
<p>0-1背包问题的通常定义是：一共有N件物品，第i件物品的重量为w[i]，价值为v[i]。在总重量不超过背包承载上限W的情况下，能够获得的最大价值是多少？每件物品可以使用<strong>0次或者1次</strong>。</p>
<p>例子：</p>
<p>重量 w = [1, 1, 2, 2]</p>
<p>价值 v = [1, 3, 4, 5]</p>
<p>背包承重 W = 4</p>
<p>最大价值为9，可以选第1,2,4件物品，也可以选第3，4件物品；总重量为4，总价值为9。</p>
<p>动态规划的状态转移方程为：</p><pre class="crayon-plain-tag">dp[i][j] = max(dp[i-1][j], dp[i][j-w[i]] + v[i])</pre><p><img class="alignnone wp-image-4295 size-full" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-large wp-image-4276" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone wp-image-4290 size-full" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-3.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-3-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone wp-image-4293 size-full" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-4.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp10-4-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-4303" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-1.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-1.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-1-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-1-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<h2><strong>Solutions</strong></h2>
<p><div class="responsive-tabs">
<h2 class="tabtitle">Search</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">def knapsack01DFS(w, v, W):
  def dfs(s, cur_w, cur_v, ans):
    ans[0] = max(ans[0], cur_v)
    if s == N: return
    for i in range(s, N):
      if cur_w + w[i] &lt;= W:
        dfs(i + 1, cur_w + w[i], cur_v + v[i], ans)
  ans = [0]
  dfs(0, 0, 0, ans)
  return ans[0]</pre><p></div><h2 class="tabtitle">DP2</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">def knapsack01(w, v, W):
  dp = [[0] * (W + 1) for _ in range(N+1)]
  for i in range(1, N + 1):
    dp[i] = dp[i-1].clone()
    for j in range(w[i], W + 1):
      dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i - 1]] + v[i - 1])
  return max(dp[N])</pre><p></div><h2 class="tabtitle">DP1/tmp</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">def knapsack01R(w, v, W):
  dp = [0] * (W + 1)
  for i in range(0, N):
    tmp = list(dp)
    for j in range(w[i], W + 1):
      tmp[j] = max(tmp[j], dp[j - w[i]] + v[i])
    dp = tmp
  return max(dp)</pre><p></div><h2 class="tabtitle">DP1/push</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">def knapsack01R2(w, v, W):
  dp = [0] * (W + 1)
  for i in range(0, N):
    for j in range(W, w[i] - 1, -1):
      dp[j] = max(dp[j], dp[j - w[i]] + v[i])
  return max(dp)</pre><p></div><h2 class="tabtitle">DP1/pull</h2>
<div class="tabcontent">
</p><pre class="crayon-plain-tag">def knapsack01R1(w, v, W):
  dp = [0] * (W + 1)
  for i in range(0, N):
    for j in range(W - w[i], -1, -1):
      dp[j + w[i]] = max(dp[j + w[i]], dp[j] + v[i])
  return max(dp)</pre><p></div></div></p>
<p>&nbsp;</p>
<h1><strong>Unbounded Knapsack Problem 完全背包</strong></h1>
<p><strong>完全背包</strong>、<strong>多重背包</strong>是常见的变形。和01背包的区别在于，完全背包每件物品可以使用<strong>无限多次</strong>，而多重背包每件物品最多可以使用<strong>n[i]次</strong>。两个问题都可以转换成01背包问题进行求解。</p>
<p>但是Naive的转换会大大增加时间复杂度：</p>
<p>完全背包：“复制”第i件物品到一共有 W/w[i] 件</p>
<p>多重背包：“复制”第i件物品到一共有 n[i] 件</p>
<p>然后直接调用01背包进行求解。</p>
<p>时间复杂度：</p>
<p>完全背包 O(Σ(W/w[i])*W)</p>
<p>多重背包 O(Σn[i]*W)</p>
<p>不难看出时间复杂度 = O(物品数量*背包承重)</p>
<p>背包承重是给定的，要降低运行时候，只有减少物品数量。但怎样才能减少总的物品数量呢？</p>
<p>这就涉及到二进制思想：任何一个正整数都可以用 (1, 2, 4, &#8230;, 2^K)的组合来表示。例如14 = 2 + 4 + 8。<br />
原本需要放入14件相同的物品，现在只需要放入3件（重量和价值是原物品的2倍，4倍，8倍）。大幅降低了总的物品数量从而降低运行时间。</p>
<p>完全背包：对于第i件物品，我们只需要创建k = log(W/w[i])件虚拟物品即可。</p>
<p>每件虚拟物品的重量和价值为：1*(w[i], v[i]), 2*(w[i], v[i]), &#8230;, 2^k*(w[i], v[i])。</p>
<p>多重背包：对于第i件物品，我们只需要创建k + 1件虚拟物品即可，其中k = log(n[i])。</p>
<p>每件虚拟物品的重量和价值为：1*(w[i], v[i]), 2*(w[i], v[i]), &#8230;, 2^(k-1)*(w[i], v[i]), 以及 (<strong>n[i] &#8211; 2^k &#8211; 1</strong>) * (w[i], v[i])。</p>
<p>例如：n[i] = 14, k = 3, 虚拟物品的倍数为 1, 2, 4 和 7，这4个数组合可以组成1 ~ 14中的任何一个数，并且不会&gt;14，即不超过n[i]。</p>
<p>二进制转换后直接调用01背包即可</p>
<p>时间复杂度：</p>
<p>完全背包 O(Σlog(W/w[i])*W)</p>
<p>多重背包 O(Σlog(n[i])*W)</p>
<p>空间复杂度 O(W)</p>
<p>其实完全背包和多重背包都可以在 O(NW)时间内完成，前者在视频中有讲到，后者属于<strong>超纲内容</strong>，以后有机会再和大家深入分享。</p>
<p><img class="alignnone size-full wp-image-4300" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-4301" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-3.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-3.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-3-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-3-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<h1><strong>Bounded Knapsack Problem 多重背包</strong></h1>
<p><img class="alignnone wp-image-4304 size-full" src="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-4.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-4.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-4-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/11/sp11-4-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/sp/knapsack-problem/">Knapsack Problem 背包问题</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/sp/knapsack-problem/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 871. Minimum Number of Refueling Stops</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-871-minimum-number-of-refueling-stops/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-871-minimum-number-of-refueling-stops/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 15 Jul 2018 06:10:52 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[0-1 knapsack]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[knapsack]]></category>
		<category><![CDATA[min count]]></category>
		<category><![CDATA[priority queue]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=3171</guid>

					<description><![CDATA[<p>Problem A car travels from a starting position to a destination which is target miles east of the starting position. Along the way, there are gas stations. &#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-871-minimum-number-of-refueling-stops/">花花酱 LeetCode 871. Minimum Number of Refueling Stops</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/vWTPA5zw24M?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<h1><strong>Problem</strong></h1>
<p>A car travels from a starting position to a destination which is <code>target</code> miles east of the starting position.</p>
<p>Along the way, there are gas stations.  Each <code>station[i]</code> represents a gas station that is <code>station[i][0]</code> miles east of the starting position, and has <code>station[i][1]</code> liters of gas.</p>
<p>The car starts with an infinite tank of gas, which initially has <code>startFuel</code> liters of fuel in it.  It uses 1 liter of gas per 1 mile that it drives.</p>
<p>When the car reaches a gas station, it may stop and refuel, transferring all the gas from the station into the car.</p>
<p>What is the least number of refueling stops the car must make in order to reach its destination?  If it cannot reach the destination, return <code>-1</code>.</p>
<p>Note that if the car reaches a gas station with 0 fuel left, the car can still refuel there.  If the car reaches the destination with 0 fuel left, it is still considered to have arrived.</p>
<div>
<p><strong>Example 1:</strong></p>
<pre class="crayon:false"><strong>Input: </strong>target = <span id="example-input-1-1">1</span>, startFuel = <span id="example-input-1-2">1</span>, stations = <span id="example-input-1-3">[]</span>
<strong>Output: </strong><span id="example-output-1">0</span>
<strong>Explanation: </strong>We can reach the target without refueling.
</pre>
<p><strong>Example 2:</strong></p>
<pre class="crayon:false"><strong>Input: </strong>target = <span id="example-input-2-1">100</span>, startFuel = <span id="example-input-2-2">1</span>, stations = <span id="example-input-2-3">[[10,100]]</span>
<strong>Output: </strong><span id="example-output-2">-1</span>
<strong>Explanation: </strong>We can't reach the target (or even the first gas station).
</pre>
<p><strong>Example 3:</strong></p>
<pre class="crayon:false"><strong>Input: </strong>target = <span id="example-input-3-1">100</span>, startFuel = <span id="example-input-3-2">10</span>, stations = <span id="example-input-3-3">[[10,60],[20,30],[30,30],[60,40]]</span>
<strong>Output: </strong><span id="example-output-3">2</span>
<strong>Explanation: </strong>
We start with 10 liters of fuel.
We drive to position 10, expending 10 liters of fuel.  We refuel from 0 liters to 60 liters of gas.
Then, we drive from position 10 to position 60 (expending 50 liters of fuel),
and refuel from 10 liters to 50 liters of gas.  We then drive to and reach the target.
We made 2 refueling stops along the way, so we return 2.
</pre>
<p><strong>Note:</strong></p>
<ol>
<li><code>1 &lt;= target, startFuel, stations[i][1] &lt;= 10^9</code></li>
<li><code>0 &lt;= stations.length &lt;= 500</code></li>
<li><code>0 &lt; stations[0][0] &lt; stations[1][0] &lt; ... &lt; stations[stations.length-1][0] &lt; target</code></li>
</ol>
<h1><img class="alignnone size-full wp-image-3204" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/07/871-ep207.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/07/871-ep207.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/07/871-ep207-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/07/871-ep207-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></h1>
<h1><strong>Solution1: DP</strong></h1>
<p>Time complexity: O(n^2)</p>
<p>Space complexity: O(n)</p>
<p>C++</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 24 ms
class Solution {
public:
  int minRefuelStops(int target, int startFuel, vector&lt;vector&lt;int&gt;&gt;&amp; stations) {
    const int n = stations.size();
    // dp[i]: max distance to go with i stops.
    vector&lt;long&gt; dp(n + 1, startFuel);
    // For each station
    for (int i = 0; i &lt; n; ++i) 
      // for j stops, start from high to low to avoid reusing station i
      for (int j = i + 1; j &gt;= 1; --j) 
        if (dp[j - 1] &gt;= stations[i][0])
          // if we can reach station i with j - 1 stops,
          // we can reach dp[j - 1] + station[i][1] with j stops.
          dp[j] = max(dp[j], dp[j - 1] + stations[i][1]);
    
    for (int i = 0; i &lt; dp.size(); ++i)
      if (dp[i] &gt;= target) return i;
    return -1;
  }
};</pre><p></p>
<h1><strong>Solution2: Priority Queue</strong></h1>
<p>Time complexity: O(nlogn)</p>
<p>Space complexity: O(n)</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 16 ms
class Solution {
public:
  int minRefuelStops(int target, int startFuel, vector&lt;vector&lt;int&gt;&gt;&amp; stations) {
    int cur = startFuel;
    int stops = 0;
    int i = 0;
    priority_queue&lt;int&gt; q; // gas (high to low) of reachable stations.
    while (true) {
      if (cur &gt;= target) return stops;
      while (i &lt; stations.size() &amp;&amp; stations[i][0] &lt;= cur)
        q.push(stations[i++][1]); 
      if (q.empty()) break;
      cur += q.top(); q.pop();
      ++stops;
    }
    return -1;
  }
};</pre><p>V2: Iterator</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 12 ms
class Solution {
public:
  int minRefuelStops(int target, int startFuel, vector&lt;vector&lt;int&gt;&gt;&amp; stations) {
    int cur = startFuel;
    int stops = 0;
    priority_queue&lt;int&gt; q; // gas (high to low) of reachable stations.
    auto it = begin(stations);
    while (true) {
      if (cur &gt;= target) return stops;
      while (it != end(stations) &amp;&amp; it-&gt;at(0) &lt;= cur)
        q.push(it++-&gt;at(1));
      if (q.empty()) break;
      cur += q.top(); q.pop();
      ++stops;
    }
    return -1;
  }
};</pre><p></p>
<h1><strong>Related Problems</strong></h1>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/dynamic-programming/leetcode-322-coin-change/">花花酱 LeetCode 322. Coin Change</a></li>
</ul>
</div>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-871-minimum-number-of-refueling-stops/">花花酱 LeetCode 871. Minimum Number of Refueling Stops</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-871-minimum-number-of-refueling-stops/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 518. Coin Change 2</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-518-coin-change-2/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-518-coin-change-2/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sat, 03 Mar 2018 05:57:43 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[counting]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[knapsack]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=1910</guid>

					<description><![CDATA[<p>题目大意：给你一些硬币的面值，问使用这些硬币（无限多块）能够组成amount的方法有多少种。 You are given coins of different denominations and a total amount of money. Write a function to compute the number of combinations that make&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-518-coin-change-2/">花花酱 LeetCode 518. Coin Change 2</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>题目大意：给你一些硬币的面值，问使用这些硬币（无限多块）能够组成amount的方法有多少种。</p>
<p>You are given coins of different denominations and a total amount of money. Write a function to compute the number of combinations that make up that amount. You may assume that you have infinite number of each kind of coin.</p>
<p><b>Note:</b> You can assume that</p>
<ul>
<li>0 &lt;= amount &lt;= 5000</li>
<li>1 &lt;= coin &lt;= 5000</li>
<li>the number of coins is less than 500</li>
<li>the answer is guaranteed to fit into signed 32-bit integer</li>
</ul>
<p><b>Example 1:</b></p><pre class="crayon-plain-tag">Input: amount = 5, coins = [1, 2, 5]
Output: 4
Explanation: there are four ways to make up the amount:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1</pre><p><b>Example 2:</b></p><pre class="crayon-plain-tag">Input: amount = 3, coins = [2]
Output: 0
Explanation: the amount of 3 cannot be made up just with coins of 2.</pre><p><b>Example 3:</b></p><pre class="crayon-plain-tag">Input: amount = 10, coins = [10] 
Output: 1</pre><p><strong>Idea: DP</strong></p>
<p><strong>Transition 1:</strong></p>
<p>Let us use dp[i][j] to denote the number of ways to sum up to amount j using first i kind of coins.</p>
<p>dp[i][j] = dp[i &#8211; 1][j &#8211; coin] + dp[i &#8211; 1][j &#8211; 2* coin] + &#8230;</p>
<p>Time complexity: O(n*amount^2) TLE</p>
<p>Space complexity: O(n*amount) -&gt; O(amount)</p>
<p><strong>Transition 2:</strong></p>
<p>Let us use dp[i] to denote the number of ways to sum up to amount i.</p>
<p>dp[i + coin] += dp[i]</p>
<p>Time complexity: O(n*amount)</p>
<p>Space complexity:  O(amount)</p>
<p>C++</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 4 ms
class Solution {
public:
  int change(int amount, vector&lt;int&gt;&amp; coins) {
    vector&lt;int&gt; dp(amount + 1, 0);
    dp[0] = 1;
    for (const int coin : coins)
      for (int i = 0; i &lt;= amount - coin; ++i)
        dp[i + coin] += dp[i];      
    return dp[amount];
  }
};</pre><p>Java</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 7 ms
class Solution {
  public int change(int amount, int[] coins) {
    int[] dp = new int[amount + 1];
    dp[0] = 1;
    for (int coin : coins)
      for (int i = 0; i &lt;= amount - coin; ++i)
        dp[i + coin] += dp[i];
    return dp[amount];
  }
}</pre><p>Python</p><pre class="crayon-plain-tag">"""
Author: Huahua
Running time: 107 ms (beats 100%)
"""
class Solution(object):
  def change(self, amount, coins):
    dp = [1] + [0] * (amount);    
    for coin in coins:
      for i in xrange(amount - coin + 1):
        if dp[i]:
          dp[i + coin] += dp[i]
    return dp[amount]</pre><p>&nbsp;</p>
<p><strong>Related Problems:</strong></p>
<ul>
<li><a href="http://zxi.mytechroad.com/blog/dynamic-programming/leetcode-322-coin-change/">花花酱 LeetCode 322. Coin Change</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-518-coin-change-2/">花花酱 LeetCode 518. Coin Change 2</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-518-coin-change-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 322. Coin Change</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-322-coin-change/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-322-coin-change/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Wed, 03 Jan 2018 03:50:16 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[Medium]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[knapsack]]></category>
		<category><![CDATA[medium]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=1469</guid>

					<description><![CDATA[<p>题目大意：给你一些不同币值的硬币，问你最少需要多少个硬币才能组成amount，假设每种硬币有无穷多个。 Problem: You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-322-coin-change/">花花酱 LeetCode 322. Coin Change</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/uUETHdijzkA?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p>题目大意：给你一些不同币值的硬币，问你最少需要多少个硬币才能组成amount，假设每种硬币有无穷多个。</p>
<p><strong>Problem:</strong></p>
<p>You are given coins of different denominations and a total amount of money <i>amount</i>. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return <code>-1</code>.</p>
<p><b>Example 1:</b><br />
coins = <code>[1, 2, 5]</code>, amount = <code>11</code><br />
return <code>3</code> (11 = 5 + 5 + 1)</p>
<p><b>Example 2:</b><br />
coins = <code>[2]</code>, amount = <code>3</code><br />
return <code>-1</code>.</p>
<p><strong>Idea:</strong></p>
<p>DP /knapsack</p>
<p>Search</p>
<p><img class="alignnone wp-image-1479 size-full" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/322-ep148.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/322-ep148.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/322-ep148-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/322-ep148-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><img class="alignnone size-full wp-image-1477" src="http://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/322-ep148-2.png" alt="" width="960" height="540" srcset="https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/322-ep148-2.png 960w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/322-ep148-2-300x169.png 300w, https://zxi.mytechroad.com/blog/wp-content/uploads/2018/01/322-ep148-2-768x432.png 768w" sizes="(max-width: 960px) 100vw, 960px" /></p>
<p><strong>Solution1:</strong></p>
<p>C++ / DP</p>
<p>Time complexity: O(n*amount^2)</p>
<p>Space complexity: O(amount)</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 189 ms
class Solution {
public:
    int coinChange(vector&lt;int&gt;&amp; coins, int amount) {
        vector&lt;int&gt; dp(amount + 1, INT_MAX);
        dp[0] = 0;
        for (auto coin : coins) {
            for (int i = amount - coin; i &gt;= 0; --i)
                if (dp[i] != INT_MAX)
                    for (int k = 1; k * coin + i &lt;= amount; ++k)
                        dp[i + k * coin] = min(dp[i + k * coin], dp[i] + k);
        }
        
        return dp[amount] == INT_MAX ? -1 : dp[amount];
    }
};</pre><p><strong>Solution2:</strong></p>
<p>C++ / DP</p>
<p>Time complexity: O(n*amount)</p>
<p>Space complexity: O(amount)</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 16 ms
class Solution {
public:
    int coinChange(vector&lt;int&gt;&amp; coins, int amount) {
        // dp[i] = min coins to make up to amount i
        vector&lt;int&gt; dp(amount + 1, INT_MAX);
        dp[0] = 0;
        for (int coin : coins) {
            for (int i = coin; i &lt;= amount; ++i)
                if (dp[i - coin] != INT_MAX)  
                    dp[i] = min(dp[i], dp[i - coin] + 1);
        }
        
        return dp[amount] == INT_MAX ? -1 : dp[amount];
    }
};</pre><p>Python3</p><pre class="crayon-plain-tag">"""
Author: Huahua
Running time: 632 ms beats 90.27%
"""
class Solution:
  def coinChange(self, coins, amount):
    INVALID = 2**32
    dp = [INVALID] * (amount + 1)
    dp[0] = 0
    for coin in coins:
      for i in range(coin, amount + 1):
        if dp[i - coin] &gt;= dp[i]: continue
        dp[i] = dp[i - coin] + 1
    return -1 if dp[amount] == INVALID else dp[amount]</pre><p><strong>Solution3:</strong></p>
<p>C++ / DFS</p>
<p>Time complexity: O(amount^n/(coin_0*coin_1*&#8230;*coin_n))</p>
<p>Space complexity: O(n)</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 6 ms
class Solution {
public:
    int coinChange(vector&lt;int&gt;&amp; coins, int amount) {
        // Sort coins in desending order
        std::sort(coins.rbegin(), coins.rend());
        int ans = INT_MAX;
        coinChange(coins, 0, amount, 0, ans);
        return ans == INT_MAX ? -1 : ans;
    }
private:
    void coinChange(const vector&lt;int&gt;&amp; coins, 
                    int s, int amount, int count, int&amp; ans) {
        if (amount == 0) {
            ans = min(ans, count);
            return;
        }
        
        if (s == coins.size()) return;
        
        const int coin = coins[s];                
        for (int k = amount / coin; k &gt;= 0 &amp;&amp; count + k &lt; ans; k--)
            coinChange(coins, s + 1, amount - k * coin, count + k, ans);
    }    
};</pre><p>Python3</p><pre class="crayon-plain-tag">"""
Author: Huahua
Running time: 200ms
"""
class Solution:
  def coinChange(self, coins, amount):
    coins.sort(reverse=True)
    INVALID = 10**10
    self.ans = INVALID
    def dfs(s, amount, count):      
      if amount == 0:
        self.ans = count
        return
      if s == len(coins): return
      
      coin = coins[s]
      for k in range(amount // coin, -1, -1):
        if count + k &gt;= self.ans: break
        dfs(s + 1, amount - k * coin, count + k)
    dfs(0, amount, 0)
    return -1 if self.ans == INVALID else self.ans</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-322-coin-change/">花花酱 LeetCode 322. Coin Change</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-322-coin-change/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>花花酱 LeetCode 416. Partition Equal Subset Sum</title>
		<link>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-416-partition-equal-subset-sum/</link>
					<comments>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-416-partition-equal-subset-sum/#respond</comments>
		
		<dc:creator><![CDATA[zxi]]></dc:creator>
		<pubDate>Sun, 31 Dec 2017 22:41:36 +0000</pubDate>
				<category><![CDATA[Dynamic Programming]]></category>
		<category><![CDATA[Medium]]></category>
		<category><![CDATA[dp]]></category>
		<category><![CDATA[knapsack]]></category>
		<guid isPermaLink="false">http://zxi.mytechroad.com/blog/?p=1381</guid>

					<description><![CDATA[<p>题目大意： 给你一个正整数的数组，问你能否把元素划分成元素和相等的两组。 Problem: Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in&#8230;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-416-partition-equal-subset-sum/">花花酱 LeetCode 416. Partition Equal Subset Sum</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="500" height="375" src="https://www.youtube.com/embed/r6I-ikllNDM?feature=oembed" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen></iframe></p>
<p>题目大意：</p>
<p>给你一个正整数的数组，问你能否把元素划分成元素和相等的两组。</p>
<p><strong>Problem:</strong></p>
<p>Given a <b>non-empty</b> array containing <b>only positive integers</b>, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.</p>
<p><b>Note:</b></p>
<ol>
<li>Each of the array element will not exceed 100.</li>
<li>The array size will not exceed 200.</li>
</ol>
<p><b>Example 1:</b></p><pre class="crayon-plain-tag">Input: [1, 5, 11, 5]

Output: true

Explanation: The array can be partitioned as [1, 5, 5] and [11].</pre><p><b>Example 2:</b></p><pre class="crayon-plain-tag">Input: [1, 2, 3, 5]

Output: false

Explanation: The array cannot be partitioned into equal sum subsets.</pre><p>&nbsp;</p>
<p><strong>Idea:</strong></p>
<p>DP 动态规划</p>
<p><strong>Solution:</strong></p>
<p>Time complexity: O(n*sum)</p>
<p>Space complexity: O(sum)</p>
<p>C++</p><pre class="crayon-plain-tag">// Author: Huahua
// Running time: 16 ms
class Solution {
public:
    bool canPartition(vector&lt;int&gt;&amp; nums) {
        const int sum = std::accumulate(nums.begin(), nums.end(), 0);
        if (sum % 2 != 0) return false;
        vector&lt;int&gt; dp(sum + 1, 0);
        dp[0] = 1;
        for (const int num : nums) {
            for (int i = sum; i &gt;= 0; --i)
                if (dp[i]) dp[i + num] = 1;
            if (dp[sum / 2]) return true;
        }
        return false;
    }
};</pre><p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-416-partition-equal-subset-sum/">花花酱 LeetCode 416. Partition Equal Subset Sum</a> appeared first on <a rel="nofollow" href="https://zxi.mytechroad.com/blog">Huahua&#039;s Tech Road</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-416-partition-equal-subset-sum/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
