数组的最大与和
你需要把所有 n 个整数分到这些篮子中,且每个篮子 至多 有 2 个整数。
一种分配方案的与和定义为每个数与它所在篮子编号的 按位与运算结果之和。
请你返回将 nums 中所有数放入 numSlots 个篮子中的最大与和。
1. 状态压缩 + 动态规划
这里的状态压缩就是枚举篮子的全部状态
数的放置没有先后之分,我们固定数的访问顺序,用于计算与和
同时把当前数,赋给任意空篮子,用于计算下一个状态的最大与和,同时可以保证无后小性
因为下一个状态,只会在当前状态更新后,再被遍历访问到
class Solution {
public:
int maximumANDSum(vector<int> &nums, int numSlots) {
int ans = 0;
//从前往后依次放数,并记录对应状态最大和
vector<int> f(1 << (numSlots * 2)); //存储所有篮子状态
for (int i = 0; i < f.size(); ++i) { //遍历所有状态
int c = __builtin_popcount(i); //下一个数的坐标
if (c >= nums.size()) continue; //数不够的情况跳过
for (int j = 0; j < numSlots * 2; ++j) { //枚举当前状态的每一个篮子
if ((i & (1 << j)) == 0) { // 枚举空篮子 j
int s = i | (1 << j); //给该篮子添加下一个数的状态,该状态必然比当前枚举状态大,所以只会在后面被计算到,保证了无后效性
f[s] = max(f[s], f[i] + ((j / 2 + 1) & nums[c])); //更新状态最大值
ans = max(ans, f[s]);
}
}
}
return ans;
}
};