数组的最大与和

你需要把所有 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;
    }
};
posted @ 2023-07-02 00:54  失控D大白兔  阅读(12)  评论(0编辑  收藏  举报