Leetcode周赛280_数组的最大与和

给你一个长度为 n 的整数数组 nums 和一个整数 numSlots ,满足2 * numSlots >= n 。总共有 numSlots 个篮子,编号为 1 到 numSlots 。

你需要把所有 n 个整数分到这些篮子中,且每个篮子 至多 有 2 个整数。一种分配方案的 与和 定义为每个数与它所在篮子编号的 按位与运算 结果之和。

比方说,将数字 [1, 3] 放入篮子 1 中,[4, 6] 放入篮子 2 中,这个方案的与和为 (1 AND 1) + (3 AND 1) + (4 AND 2) + (6 AND 2) = 1 + 1 + 0 + 2 = 4 。
请你返回将 nums 中所有数放入 numSlots 个篮子中的最大与和。

示例 1:

输入:nums = [1,2,3,4,5,6], numSlots = 3
输出:9
解释:一个可行的方案是 [1, 4] 放入篮子 1 中,[2, 6] 放入篮子 2 中,[3, 5] 放入篮子 3 中。
最大与和为 (1 AND 1) + (4 AND 1) + (2 AND 2) + (6 AND 2) + (3 AND 3) + (5 AND 3) = 1 + 0 + 2 + 2 + 3 + 1 = 9 。
示例 2:

输入:nums = [1,3,10,4,7,1], numSlots = 9
输出:24
解释:一个可行的方案是 [1, 1] 放入篮子 1 中,[3] 放入篮子 3 中,[4] 放入篮子 4 中,[7] 放入篮子 7 中,[10] 放入篮子 9 中。
最大与和为 (1 AND 1) + (1 AND 1) + (3 AND 3) + (4 AND 4) + (7 AND 7) + (10 AND 9) = 1 + 1 + 3 + 4 + 7 + 8 = 24 。
注意,篮子 2 ,5 ,6 和 8 是空的,这是允许的。
 

提示:

n == nums.length
1 <= numSlots <= 9
1 <= n <= 2 * numSlots
1 <= nums[i] <= 15

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-and-sum-of-array
 

解法:

看数据范围应该用状压dp,但比赛时没想到。由于篮子编号是不变的,我们可以篮子来定义状态,每个篮子最多放两个,那么我们可以用一个2*numSlots位的二进制数表示状态,其中1表示该篮子已经被占用了,0表示还未被占用。一个二进制状态mask中1的数量为c,表示前c个数字已经被分配,接下去要去分配第c+1个。

class Solution {
public:
    int maximumANDSum(vector<int>& nums, int numSlots) {
        int len = nums.size();
        int top = 1 << (numSlots * 2);
        vector<int> dp(top);
        int ans=0;
        for(int mask = 0; mask < top; ++mask)
        {
            int i = __builtin_popcount(mask);
            if(i >= len)
                continue;
            for(int j = 0; j < numSlots * 2; ++j)
            {
                
                if((mask & (1<<j)) == 0)
                {
                    int temp = 0;
                    if( j+1 > numSlots)
                        temp = (j+1 - numSlots) & nums[i];
                    else 
                        temp = (j+1) & nums[i];
                    dp[mask|(1<<j)]=max(dp[mask|(1<<j)], dp[mask] + temp);
                    ans = max(ans, dp[mask|(1<<j)]); 
                }
            }
        }
        return ans;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值