|
50 | 50 |
|
51 | 51 | <!-- 这里可写通用的实现逻辑 -->
|
52 | 52 |
|
| 53 | +**方法一:状态压缩 + 动态规划** |
| 54 | + |
| 55 | +由于每个篮子最多只能放两个数,我们不妨将篮子数乘以 $2$,这样每个篮子最多只能放一个数。 |
| 56 | + |
| 57 | +接下来,我们定义 $f[i]$ 表示篮子状态为 $i$ 时的最大与和,其中 $i$ 是一个二进制数,表示每个篮子是否放了数。初始时 $f[0]=0$。 |
| 58 | + |
| 59 | +接下来,我们考虑 $f[i]$ 如何进行状态转移。 |
| 60 | + |
| 61 | +我们可以枚举 $i$,记 $i$ 的二进制表示中 $1$ 的个数为 $cnt$。如果 $cnt \gt n$,那么 $i$ 不是一个合法的状态,我们可以直接跳过。否则,我们可以枚举 $i$ 的二进制表示中的每一位 $j$,如果 $i$ 的第 $j$ 位为 $1$,那么我们可以将第 $(cnt-1)$ 个数 $nums[cnt-1]$ 放入第 $j$ 个篮子中,此时有: |
| 62 | + |
| 63 | +$$ |
| 64 | +f[i] = \max\{f[i], f[i \oplus (1 << j)] + (nums[cnt-1] \wedge (j / 2 + 1))\} |
| 65 | +$$ |
| 66 | + |
| 67 | +其中 $\oplus$ 表示异或运算,而 $\wedge$ 表示按位与运算。 |
| 68 | + |
| 69 | +答案为 $\max\{f[i]\}$。 |
| 70 | + |
| 71 | +时间复杂度 $O(4^k \times k \times 2)$,空间复杂度 $O(4^k)$。其中 $k$ 表示篮子的数量,即题目中的 $numSlots$。 |
| 72 | + |
53 | 73 | <!-- tabs:start -->
|
54 | 74 |
|
55 | 75 | ### **Python3**
|
56 | 76 |
|
57 | 77 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
58 | 78 |
|
59 | 79 | ```python
|
60 |
| - |
| 80 | +class Solution: |
| 81 | + def maximumANDSum(self, nums: List[int], numSlots: int) -> int: |
| 82 | + n = len(nums) |
| 83 | + m = numSlots << 1 |
| 84 | + f = [0] * (1 << m) |
| 85 | + for i in range(1 << m): |
| 86 | + cnt = i.bit_count() |
| 87 | + if cnt > n: |
| 88 | + continue |
| 89 | + for j in range(m): |
| 90 | + if i >> j & 1: |
| 91 | + f[i] = max(f[i], f[i ^ (1 << j)] + (nums[cnt - 1] & (j // 2 + 1))) |
| 92 | + return max(f) |
61 | 93 | ```
|
62 | 94 |
|
63 | 95 | ### **Java**
|
64 | 96 |
|
65 | 97 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
66 | 98 |
|
67 | 99 | ```java
|
| 100 | +class Solution { |
| 101 | + public int maximumANDSum(int[] nums, int numSlots) { |
| 102 | + int n = nums.length; |
| 103 | + int m = numSlots << 1; |
| 104 | + int[] f = new int[1 << m]; |
| 105 | + int ans = 0; |
| 106 | + for (int i = 0; i < 1 << m; ++i) { |
| 107 | + int cnt = Integer.bitCount(i); |
| 108 | + if (cnt > n) { |
| 109 | + continue; |
| 110 | + } |
| 111 | + for (int j = 0; j < m; ++j) { |
| 112 | + if ((i >> j & 1) == 1) { |
| 113 | + f[i] = Math.max(f[i], f[i ^ (1 << j)] + (nums[cnt - 1] & (j / 2 + 1))); |
| 114 | + } |
| 115 | + } |
| 116 | + ans = Math.max(ans, f[i]); |
| 117 | + } |
| 118 | + return ans; |
| 119 | + } |
| 120 | +} |
| 121 | +``` |
68 | 122 |
|
| 123 | +### **C++** |
| 124 | + |
| 125 | +```cpp |
| 126 | +class Solution { |
| 127 | +public: |
| 128 | + int maximumANDSum(vector<int>& nums, int numSlots) { |
| 129 | + int n = nums.size(); |
| 130 | + int m = numSlots << 1; |
| 131 | + int f[1 << m]; |
| 132 | + memset(f, 0, sizeof(f)); |
| 133 | + for (int i = 0; i < 1 << m; ++i) { |
| 134 | + int cnt = __builtin_popcount(i); |
| 135 | + if (cnt > n) { |
| 136 | + continue; |
| 137 | + } |
| 138 | + for (int j = 0; j < m; ++j) { |
| 139 | + if (i >> j & 1) { |
| 140 | + f[i] = max(f[i], f[i ^ (1 << j)] + (nums[cnt - 1] & (j / 2 + 1))); |
| 141 | + } |
| 142 | + } |
| 143 | + } |
| 144 | + return *max_element(f, f + (1 << m)); |
| 145 | + } |
| 146 | +}; |
| 147 | +``` |
| 148 | +
|
| 149 | +### **Go** |
| 150 | +
|
| 151 | +```go |
| 152 | +func maximumANDSum(nums []int, numSlots int) (ans int) { |
| 153 | + n := len(nums) |
| 154 | + m := numSlots << 1 |
| 155 | + f := make([]int, 1<<m) |
| 156 | + for i := range f { |
| 157 | + cnt := bits.OnesCount(uint(i)) |
| 158 | + if cnt > n { |
| 159 | + continue |
| 160 | + } |
| 161 | + for j := 0; j < m; j++ { |
| 162 | + if i>>j&1 == 1 { |
| 163 | + f[i] = max(f[i], f[i^(1<<j)]+(nums[cnt-1]&(j/2+1))) |
| 164 | + } |
| 165 | + } |
| 166 | + ans = max(ans, f[i]) |
| 167 | + } |
| 168 | + return |
| 169 | +} |
| 170 | +
|
| 171 | +func max(a, b int) int { |
| 172 | + if a > b { |
| 173 | + return a |
| 174 | + } |
| 175 | + return b |
| 176 | +} |
69 | 177 | ```
|
70 | 178 |
|
71 | 179 | ### **TypeScript**
|
72 | 180 |
|
73 | 181 | ```ts
|
74 |
| - |
| 182 | +function maximumANDSum(nums: number[], numSlots: number): number { |
| 183 | + const n = nums.length; |
| 184 | + const m = numSlots << 1; |
| 185 | + const f: number[] = new Array(1 << m).fill(0); |
| 186 | + for (let i = 0; i < 1 << m; ++i) { |
| 187 | + const cnt = i |
| 188 | + .toString(2) |
| 189 | + .split('') |
| 190 | + .filter(c => c === '1').length; |
| 191 | + if (cnt > n) { |
| 192 | + continue; |
| 193 | + } |
| 194 | + for (let j = 0; j < m; ++j) { |
| 195 | + if (((i >> j) & 1) === 1) { |
| 196 | + f[i] = Math.max( |
| 197 | + f[i], |
| 198 | + f[i ^ (1 << j)] + (nums[cnt - 1] & ((j >> 1) + 1)), |
| 199 | + ); |
| 200 | + } |
| 201 | + } |
| 202 | + } |
| 203 | + return Math.max(...f); |
| 204 | +} |
75 | 205 | ```
|
76 | 206 |
|
77 | 207 | ### **...**
|
|
0 commit comments