65
65
66
66
<!-- 这里可写通用的实现逻辑 -->
67
67
68
- ** 方法一:状态压缩 DP**
68
+ ** 方法一:状态压缩动态规划**
69
+
70
+ 我们注意到 $n$ 不超过 $10$,因此我们考虑使用状态压缩动态规划的方法求解。
71
+
72
+ 我们定义 $f[ i] [ j ] $ 表示在前 $i$ 个帽子中,当前被分配的人的状态为 $j$ 时的方案数。其中 $j$ 是一个二进制数,表示当前被分配的人的集合。初始时 $f[ 0] [ 0 ] =1$,答案为 $f[ m] [ 2^n - 1 ] $,其中 $m$ 是帽子的最大编号,而 $n$ 是人的数量。
73
+
74
+ 考虑 $f[ i] [ j ] $,如果第 $i$ 个帽子不分配给任何人,那么 $f[ i] [ j ] =f[ i-1] [ j ] $;如果第 $i$ 个帽子分配给了喜欢它的人 $k$,那么 $f[ i] [ j ] =f[ i-1] [ j \oplus 2^k ] $。这里 $\oplus$ 表示异或运算。因此我们可以得到状态转移方程:
75
+
76
+ $$
77
+ f[i][j]=f[i-1][j]+ \sum_{k \in like[i]} f[i-1][j \oplus 2^k]
78
+ $$
79
+
80
+ 其中 $like[ i] $ 表示喜欢第 $i$ 个帽子的人的集合。
81
+
82
+ 最终的答案即为 $f[ m] [ 2^n - 1 ] $,注意答案可能很大,需要对 $10^9 + 7$ 取模。
83
+
84
+ 时间复杂度 $O(m \times 2^n \times n)$,空间复杂度 $O(m \times 2^n)$。其中 $m$ 是帽子的最大编号,本题中 $m \leq 40$;而 $n$ 是人的数量,本题中 $n \leq 10$。
69
85
70
86
<!-- tabs:start -->
71
87
76
92
``` python
77
93
class Solution :
78
94
def numberWays (self , hats : List[List[int ]]) -> int :
79
- d = defaultdict(list )
95
+ g = defaultdict(list )
80
96
for i, h in enumerate (hats):
81
97
for v in h:
82
- d[v].append(i)
98
+ g[v].append(i)
99
+ mod = 10 ** 9 + 7
83
100
n = len (hats)
84
- mx = max (max (h) for h in hats)
85
- dp = [[0 ] * (1 << n) for _ in range (mx + 1 )]
86
- dp[0 ][0 ] = 1
87
- mod = int (1e9 ) + 7
88
- for i in range (1 , mx + 1 ):
89
- for mask in range (1 << n):
90
- dp[i][mask] = dp[i - 1 ][mask]
91
- for j in d[i]:
92
- if (mask >> j) & 1 :
93
- dp[i][mask] += dp[i - 1 ][mask ^ (1 << j)]
94
- dp[i][mask] %= mod
95
- return dp[mx][(1 << n) - 1 ]
101
+ m = max (max (h) for h in hats)
102
+ f = [[0 ] * (1 << n) for _ in range (m + 1 )]
103
+ f[0 ][0 ] = 1
104
+ for i in range (1 , m + 1 ):
105
+ for j in range (1 << n):
106
+ f[i][j] = f[i - 1 ][j]
107
+ for k in g[i]:
108
+ if j >> k & 1 :
109
+ f[i][j] = (f[i][j] + f[i - 1 ][j ^ (1 << k)]) % mod
110
+ return f[m][- 1 ]
96
111
```
97
112
98
113
### ** Java**
@@ -101,67 +116,71 @@ class Solution:
101
116
102
117
``` java
103
118
class Solution {
104
- private static final int MOD = (int ) 1e9 + 7 ;
105
-
106
119
public int numberWays (List<List<Integer > > hats ) {
107
- List<Integer > [] d = new List [41 ];
108
- Arrays . setAll(d, k - > new ArrayList<> ());
109
120
int n = hats. size();
110
- int mx = 0 ;
121
+ int m = 0 ;
122
+ for (var h : hats) {
123
+ for (int v : h) {
124
+ m = Math . max(m, v);
125
+ }
126
+ }
127
+ List<Integer > [] g = new List [m + 1 ];
128
+ Arrays . setAll(g, k - > new ArrayList<> ());
111
129
for (int i = 0 ; i < n; ++ i) {
112
- for (int h : hats. get(i)) {
113
- d[h]. add(i);
114
- mx = Math . max(mx, h);
130
+ for (int v : hats. get(i)) {
131
+ g[v]. add(i);
115
132
}
116
133
}
117
- long [][] dp = new long [mx + 1 ][1 << n];
118
- dp[0 ][0 ] = 1 ;
119
- for (int i = 1 ; i < mx + 1 ; ++ i) {
120
- for (int mask = 0 ; mask < 1 << n; ++ mask) {
121
- dp[i][mask] = dp[i - 1 ][mask];
122
- for (int j : d[i]) {
123
- if (((mask >> j) & 1 ) == 1 ) {
124
- dp[i][mask] = (dp[i][mask] + dp[i - 1 ][mask ^ (1 << j)]) % MOD ;
134
+ final int mod = (int ) 1e9 + 7 ;
135
+ int [][] f = new int [m + 1 ][1 << n];
136
+ f[0 ][0 ] = 1 ;
137
+ for (int i = 1 ; i <= m; ++ i) {
138
+ for (int j = 0 ; j < 1 << n; ++ j) {
139
+ f[i][j] = f[i - 1 ][j];
140
+ for (int k : g[i]) {
141
+ if ((j >> k & 1 ) == 1 ) {
142
+ f[i][j] = (f[i][j] + f[i - 1 ][j ^ (1 << k)]) % mod;
125
143
}
126
144
}
127
145
}
128
146
}
129
- return ( int ) dp[mx ][(1 << n) - 1 ];
147
+ return f[m ][(1 << n) - 1 ];
130
148
}
131
149
}
132
150
```
133
151
134
152
### ** C++**
135
153
136
154
``` cpp
137
- using ll = long long ;
138
-
139
155
class Solution {
140
156
public:
141
157
int numberWays(vector<vector<int >>& hats) {
142
- vector<vector<int >> d(41);
143
158
int n = hats.size();
144
- int mx = 0;
159
+ int m = 0;
160
+ for (auto& h : hats) {
161
+ m = max(m, * max_element(h.begin(), h.end()));
162
+ }
163
+ vector<vector<int >> g(m + 1);
145
164
for (int i = 0; i < n; ++i) {
146
- for (int& h : hats[ i] ) {
147
- d[ h] .push_back(i);
148
- mx = max(mx, h);
165
+ for (int& v : hats[ i] ) {
166
+ g[ v] .push_back(i);
149
167
}
150
168
}
151
- vector<vector<ll >> dp(mx + 1, vector<ll >(1 << n));
152
- dp[ 0] [ 0 ] = 1;
153
- int mod = 1e9 + 7;
154
- for (int i = 1; i <= mx; ++i) {
155
- for (int mask = 0; mask < 1 << n; ++mask) {
156
- dp[ i] [ mask ] = dp[ i - 1] [ mask ] ;
157
- for (int& j : d[ i] ) {
158
- if ((mask >> j) & 1) {
159
- dp[ i] [ mask ] = (dp[ i] [ mask ] + dp[ i - 1] [ mask ^ (1 << j) ] ) % mod;
169
+ const int mod = 1e9 + 7;
170
+ int f[ m + 1] [ 1 << n ] ;
171
+ memset(f, 0, sizeof(f));
172
+ f[ 0] [ 0 ] = 1;
173
+ for (int i = 1; i <= m; ++i) {
174
+ for (int j = 0; j < 1 << n; ++j) {
175
+ f[ i] [ j ] = f[ i -1] [ j ] ;
176
+ for (int k : g[ i] ) {
177
+ if (j >> k & 1) {
178
+ f[ i] [ j ] = (f[ i] [ j ] + f[ i - 1] [ j ^ (1 << k) ] ) % mod;
160
179
}
161
180
}
162
181
}
163
182
}
164
- return dp [ mx ] [ (1 << n) - 1 ] ;
183
+ return f [ m ] [ (1 << n) - 1 ] ;
165
184
}
166
185
};
167
186
```
@@ -170,32 +189,36 @@ public:
170
189
171
190
```go
172
191
func numberWays(hats [][]int) int {
173
- d := make([][]int, 41)
174
- mx := 0
192
+ n := len(hats)
193
+ m := 0
194
+ for _, h := range hats {
195
+ for _, v := range h {
196
+ m = max(m, v)
197
+ }
198
+ }
199
+ g := make([][]int, m+1)
175
200
for i, h := range hats {
176
201
for _, v := range h {
177
- d[v] = append(d[v], i)
178
- mx = max(mx, v)
202
+ g[v] = append(g[v], i)
179
203
}
180
204
}
181
- dp := make([][]int, mx+1)
182
- n := len(hats )
183
- for i := range dp {
184
- dp [i] = make([]int, 1<<n)
205
+ const mod = 1e9 + 7
206
+ f := make([][]int, m+1 )
207
+ for i := range f {
208
+ f [i] = make([]int, 1<<n)
185
209
}
186
- dp[0][0] = 1
187
- mod := int(1e9) + 7
188
- for i := 1; i <= mx; i++ {
189
- for mask := 0; mask < 1<<n; mask++ {
190
- dp[i][mask] = dp[i-1][mask]
191
- for _, j := range d[i] {
192
- if ((mask >> j) & 1) == 1 {
193
- dp[i][mask] = (dp[i][mask] + dp[i-1][mask^(1<<j)]) % mod
210
+ f[0][0] = 1
211
+ for i := 1; i <= m; i++ {
212
+ for j := 0; j < 1<<n; j++ {
213
+ f[i][j] = f[i-1][j]
214
+ for _, k := range g[i] {
215
+ if j>>k&1 == 1 {
216
+ f[i][j] = (f[i][j] + f[i-1][j^(1<<k)]) % mod
194
217
}
195
218
}
196
219
}
197
220
}
198
- return dp[mx ][(1<<n)-1]
221
+ return f[m ][(1<<n)-1]
199
222
}
200
223
201
224
func max(a, b int) int {
@@ -206,6 +229,37 @@ func max(a, b int) int {
206
229
}
207
230
```
208
231
232
+ ### ** TypeScript**
233
+
234
+ ``` ts
235
+ function numberWays(hats : number [][]): number {
236
+ const n = hats .length ;
237
+ const m = Math .max (... hats .flat ());
238
+ const g: number [][] = Array .from ({ length: m + 1 }, () => []);
239
+ for (let i = 0 ; i < n ; ++ i ) {
240
+ for (const v of hats [i ]) {
241
+ g [v ].push (i );
242
+ }
243
+ }
244
+ const f: number [][] = Array .from ({ length: m + 1 }, () =>
245
+ Array .from ({ length: 1 << n }, () => 0 ),
246
+ );
247
+ f [0 ][0 ] = 1 ;
248
+ const mod = 1e9 + 7 ;
249
+ for (let i = 1 ; i <= m ; ++ i ) {
250
+ for (let j = 0 ; j < 1 << n ; ++ j ) {
251
+ f [i ][j ] = f [i - 1 ][j ];
252
+ for (const k of g [i ]) {
253
+ if (((j >> k ) & 1 ) === 1 ) {
254
+ f [i ][j ] = (f [i ][j ] + f [i - 1 ][j ^ (1 << k )]) % mod ;
255
+ }
256
+ }
257
+ }
258
+ }
259
+ return f [m ][(1 << n ) - 1 ];
260
+ }
261
+ ```
262
+
209
263
### ** ...**
210
264
211
265
```
0 commit comments