Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 557b811

Browse files
Merge pull request #774 from SharingSource/ac_oier
✨feat: add 2305
2 parents e9d0bfb + 0c71969 commit 557b811

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

‎Index/状压 DP.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
| [943. 最短超级串](https://leetcode.cn/problems/find-the-shortest-superstring/) | [LeetCode 题解链接](https://leetcode.cn/problems/find-the-shortest-superstring/solution/gong-shui-san-xie-zhuang-ya-dp-yun-yong-p6hlz/) | 困难 | 🤩🤩🤩🤩🤩 |
77
| [1994. 好子集的数目](https://leetcode-cn.com/problems/the-number-of-good-subsets/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/the-number-of-good-subsets/solution/gong-shui-san-xie-zhuang-ya-dp-yun-yong-gz4w5/) | 困难 | 🤩🤩🤩🤩 |
88
| [2044. 统计按位或能得到最大值的子集数目](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets/solution/by-ac_oier-dos6/) | 困难 | 🤩🤩🤩🤩 |
9+
| [2305. 公平分发饼干](https://leetcode.cn/problems/fair-distribution-of-cookies/) | [LeetCode 题解链接](https://leetcode.cn/problems/fair-distribution-of-cookies/solution/gong-shui-san-xie-jian-dan-zhuang-ya-dp-trg25/) | 中等 | 🤩🤩🤩🤩🤩 |
910

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[2305. 公平分发饼干](https://leetcode.cn/problems/fair-distribution-of-cookies/solution/gong-shui-san-xie-jian-dan-zhuang-ya-dp-trg25/)** ,难度为 **中等**
4+
5+
Tag : 「状压 DP」、「位运算」
6+
7+
8+
9+
给你一个整数数组 `cookies`,其中 `cookies[i]` 表示在第 `i` 个零食包中的饼干数量。另给你一个整数 `k` 表示等待分发零食包的孩子数量,所有零食包都需要分发。
10+
11+
在同一个零食包中的所有饼干都必须分发给同一个孩子,不能分开。
12+
13+
分发的不公平程度定义为单个孩子在分发过程中能够获得饼干的最大总数。
14+
15+
返回所有分发的最小不公平程度。
16+
17+
示例 1:
18+
```
19+
输入:cookies = [8,15,10,20,8], k = 2
20+
21+
输出:31
22+
23+
解释:一种最优方案是 [8,15,8] 和 [10,20] 。
24+
- 第 1 个孩子分到 [8,15,8] ,总计 8 + 15 + 8 = 31 块饼干。
25+
- 第 2 个孩子分到 [10,20] ,总计 10 + 20 = 30 块饼干。
26+
分发的不公平程度为 max(31,30) = 31 。
27+
可以证明不存在不公平程度小于 31 的分发方案。
28+
```
29+
示例 2:
30+
```
31+
输入:cookies = [6,1,3,2,2,4,1,2], k = 3
32+
33+
输出:7
34+
35+
解释:一种最优方案是 [6,1]、[3,2,2] 和 [4,1,2] 。
36+
- 第 1 个孩子分到 [6,1] ,总计 6 + 1 = 7 块饼干。
37+
- 第 2 个孩子分到 [3,2,2] ,总计 3 + 2 + 2 = 7 块饼干。
38+
- 第 3 个孩子分到 [4,1,2] ,总计 4 + 1 + 2 = 7 块饼干。
39+
分发的不公平程度为 max(7,7,7) = 7 。
40+
可以证明不存在不公平程度小于 7 的分发方案。
41+
```
42+
43+
提示:
44+
* 2ドル <= cookies.length <= 8$
45+
* 1ドル <= cookies[i] <= 10^5$
46+
* 2ドル <= k <= cookies.length$
47+
48+
---
49+
50+
### 状压 DP
51+
52+
为了方便,将 `cookies` 记为 `cs`
53+
54+
**定义 $f[i][s]$ 为考虑前 $i$ 个人,对 `cs` 的分配情况为 `s` 时的最小不公平程度**
55+
56+
其中 `s` 为一个二进制数,若 `s` 的第 `i` 位为 `1` 代表 `cs[i]` 已被分配,反之代表未分配。同时我们可以预处理 `g` 数组,`g[s] = t` 含义为选择 `cs` 状态为 `s` 时得到的饼干总和为 `t`
57+
58+
初始化只有 $f[0][0] = 0,ドル其余均为正无穷 `0x3f3f3f3f`
59+
60+
不失一般性考虑 $f[i][s]$ 该如何计算,**通过枚举第 $i$ 个小朋友所分配到的饼干情况 `p`(`s` 的子集)进行转移**:若第 $i$ 个小朋友分配到的饼干情况为 `p`,则此前 $i - 1$ 个小朋友分配到饼干情况为 $s - p,ドル前 $i - 1$ 个小朋友的最小不公平程度为 $f[i - 1][s - p],ドル当前第 $i$ 个小朋友的不公平程度为 $g[p],ドル两者中最大值可用于更新 $f[i][s]$。
61+
62+
$$
63+
f[i][s] = \min(f[i][s], \max(f[i - 1][s - p], g[p])), p \subseteq s
64+
$$
65+
66+
最终 $f[k][2^n - 1]$ 即是答案。
67+
68+
Java 代码:
69+
```Java
70+
class Solution {
71+
public int distributeCookies(int[] cs, int k) {
72+
int n = cs.length, mask = 1 << n, INF = 0x3f3f3f3f;
73+
int[] g = new int[mask];
74+
for (int s = 0; s < mask; s++) {
75+
int t = 0;
76+
for (int i = 0; i < n; i++) t += ((s >> i) & 1) == 1 ? cs[i] : 0;
77+
g[s] = t;
78+
}
79+
int[][] f = new int[k + 10][mask];
80+
for (int i = 0; i <= k; i++) Arrays.fill(f[i], INF);
81+
f[0][0] = 0;
82+
for (int i = 1; i <= k; i++) {
83+
for (int s = 0; s < mask; s++) {
84+
for (int p = s; p != 0; p = (p - 1) & s) {
85+
f[i][s] = Math.min(f[i][s], Math.max(f[i - 1][s - p], g[p]));
86+
}
87+
}
88+
}
89+
return f[k][mask - 1];
90+
}
91+
}
92+
```
93+
Python 代码:
94+
```Python
95+
class Solution:
96+
def distributeCookies(self, cs: List[int], k: int) -> int:
97+
n, mask, INF = len(cs), 1 << len(cs), 0x3f3f3f3f
98+
g = [0] * mask
99+
for s in range(mask):
100+
t = 0
101+
for i in range(n):
102+
t += cs[i] if (s >> i) & 1 == 1 else 0
103+
g[s] = t
104+
f = [[INF] * mask for _ in range(k + 10)]
105+
f[0][0] = 0
106+
for i in range(1, k + 1):
107+
for s in range(mask):
108+
p = s
109+
while p != 0:
110+
f[i][s] = min(f[i][s], max(f[i - 1][s - p], g[p]))
111+
p = (p - 1) & s
112+
return f[k][mask - 1]
113+
```
114+
C++ 代码:
115+
```C++
116+
class Solution {
117+
public:
118+
int distributeCookies(vector<int>& cs, int k) {
119+
int n = cs.size(), mask = 1 << n, INF = 0x3f3f3f3f;
120+
vector<int> g(mask, 0);
121+
for (int s = 0; s < mask; s++) {
122+
int t = 0;
123+
for (int i = 0; i < n; i++) t += ((s >> i) & 1) == 1 ? cs[i] : 0;
124+
g[s] = t;
125+
}
126+
vector<vector<int>> f(k + 10, vector<int>(mask, INF));
127+
for (int i = 0; i <= k; i++) fill(f[i].begin(), f[i].end(), INF);
128+
f[0][0] = 0;
129+
for (int i = 1; i <= k; i++) {
130+
for (int s = 0; s < mask; s++) {
131+
for (int p = s; p != 0; p = (p - 1) & s) {
132+
f[i][s] = min(f[i][s], max(f[i - 1][s - p], g[p]));
133+
}
134+
}
135+
}
136+
return f[k][mask - 1];
137+
}
138+
};
139+
```
140+
TypeScirpt 代码:
141+
```TypeScript
142+
function distributeCookies(cs: number[], k: number): number {
143+
const n = cs.length, mask = 1 << n, INF = 0x3f3f3f3f;
144+
const g = new Array(mask).fill(0);
145+
for (let s = 0; s < mask; s++) {
146+
let t = 0;
147+
for (let i = 0; i < n; i++) t += ((s >> i) & 1) === 1 ? cs[i] : 0;
148+
g[s] = t;
149+
}
150+
const f = new Array(k + 10).fill(0).map(() => new Array(mask).fill(INF));
151+
f[0][0] = 0;
152+
for (let i = 1; i <= k; i++) {
153+
for (let s = 0; s < mask; s++) {
154+
for (let p = s; p != 0; p = (p - 1) & s) {
155+
f[i][s] = Math.min(f[i][s], Math.max(f[i - 1][s - p], g[p]));
156+
}
157+
}
158+
}
159+
return f[k][mask - 1];
160+
};
161+
```
162+
* 时间复杂度:将 `cs` 长度记为 $n,ドル状态数量记为 $m = 2^n,ドル预处理复杂度为 $O(n \times m)$;`DP` 过程需要枚举二进制长度为 $n$ 的所有子集的子集,复杂度为 $O(3^n),ドル`DP` 过程复杂度为 $O(k \times 3^n)$。整体复杂度为 $O(k \times 3^n)$
163+
* 空间复杂度:$O(k \times m)$
164+
165+
---
166+
167+
### 最后
168+
169+
这是我们「刷穿 LeetCode」系列文章的第 `No.2305` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
170+
171+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
172+
173+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
174+
175+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
176+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /