This commit is contained in:
krahets
2023-08-22 13:50:12 +08:00
parent 0c9bf14e20
commit 92a0853ab8
64 changed files with 478 additions and 479 deletions
+11 -11
View File
@@ -15,7 +15,7 @@ status: new
![最大容量问题的示例数据](max_capacity_problem.assets/max_capacity_example.png)
<p align="center"> 图最大容量问题的示例数据 </p>
<p align="center"> 图 15-7 &nbsp; 最大容量问题的示例数据 </p>
容器由任意两个隔板围成,**因此本题的状态为两个隔板的索引,记为 $[i, j]$** 。
@@ -29,30 +29,30 @@ $$
### 1. &nbsp; 贪心策略确定
这道题还有更高效率的解法。如图所示,现选取一个状态 $[i, j]$ ,其满足索引 $i < j$ 且高度 $ht[i] < ht[j]$ ,即 $i$ 为短板、 $j$ 为长板。
这道题还有更高效率的解法。如图 15-8 所示,现选取一个状态 $[i, j]$ ,其满足索引 $i < j$ 且高度 $ht[i] < ht[j]$ ,即 $i$ 为短板、 $j$ 为长板。
![初始状态](max_capacity_problem.assets/max_capacity_initial_state.png)
<p align="center"> 图初始状态 </p>
<p align="center"> 图 15-8 &nbsp; 初始状态 </p>
图所示,**若此时将长板 $j$ 向短板 $i$ 靠近,则容量一定变小**。这是因为在移动长板 $j$ 后:
如图 15-9 所示,**若此时将长板 $j$ 向短板 $i$ 靠近,则容量一定变小**。这是因为在移动长板 $j$ 后:
- 宽度 $j-i$ 肯定变小。
- 高度由短板决定,因此高度只可能不变( $i$ 仍为短板)或变小(移动后的 $j$ 成为短板)。
![向内移动长板后的状态](max_capacity_problem.assets/max_capacity_moving_long_board.png)
<p align="center"> 图向内移动长板后的状态 </p>
<p align="center"> 图 15-9 &nbsp; 向内移动长板后的状态 </p>
反向思考,**我们只有向内收缩短板 $i$ ,才有可能使容量变大**。因为虽然宽度一定变小,**但高度可能会变大**(移动后的短板 $i$ 可能会变长)。例如在图中,移动短板后面积变大。
反向思考,**我们只有向内收缩短板 $i$ ,才有可能使容量变大**。因为虽然宽度一定变小,**但高度可能会变大**(移动后的短板 $i$ 可能会变长)。例如在图 15-10 中,移动短板后面积变大。
![向内移动短板后的状态](max_capacity_problem.assets/max_capacity_moving_short_board.png)
<p align="center"> 图向内移动短板后的状态 </p>
<p align="center"> 图 15-10 &nbsp; 向内移动短板后的状态 </p>
由此便可推出本题的贪心策略:初始化两指针分裂容器两端,每轮向内收缩短板对应的指针,直至两指针相遇。
图展示了贪心策略的执行过程。
15-11 展示了贪心策略的执行过程。
1. 初始状态下,指针 $i$ , $j$ 分列与数组两端。
2. 计算当前状态的容量 $cap[i, j]$ ,并更新最大容量。
@@ -86,7 +86,7 @@ $$
=== "<9>"
![max_capacity_greedy_step9](max_capacity_problem.assets/max_capacity_greedy_step9.png)
<p align="center"> 图最大容量问题的贪心过程 </p>
<p align="center"> 图 15-11 &nbsp; 最大容量问题的贪心过程 </p>
### 2. &nbsp; 代码实现
@@ -301,7 +301,7 @@ $$
之所以贪心比穷举更快,是因为每轮的贪心选择都会“跳过”一些状态。
比如在状态 $cap[i, j]$ 下,$i$ 为短板、$j$ 为长板。若贪心地将短板 $i$ 向内移动一格,会导致图所示的状态被“跳过”。**这意味着之后无法验证这些状态的容量大小**。
比如在状态 $cap[i, j]$ 下,$i$ 为短板、$j$ 为长板。若贪心地将短板 $i$ 向内移动一格,会导致图 15-12 所示的状态被“跳过”。**这意味着之后无法验证这些状态的容量大小**。
$$
cap[i, i+1], cap[i, i+2], \dots, cap[i, j-2], cap[i, j-1]
@@ -309,7 +309,7 @@ $$
![移动短板导致被跳过的状态](max_capacity_problem.assets/max_capacity_skipped_states.png)
<p align="center"> 图移动短板导致被跳过的状态 </p>
<p align="center"> 图 15-12 &nbsp; 移动短板导致被跳过的状态 </p>
观察发现,**这些被跳过的状态实际上就是将长板 $j$ 向内移动的所有状态**。而在第二步中,我们已经证明内移长板一定会导致容量变小。也就是说,被跳过的状态都不可能是最优解,**跳过它们不会导致错过最优解**。