15303105423 发表于 2025-7-3 15:43:50

GESP2023年五级题烹饪问题:从暴力枚举到位运算优化深度解...



https://dajuwangluo.cn/zb_users/upload/2025/06/202506061749182940215106.jpg一、题目分析我们需要在N种食材中找到两种食材,使得它们美味度的按位与运算结果最大。直接暴力枚举所有组合的时间复杂度是O(N²),对于大数据量会超时。我们需要更高效的算法。二、高效解法思路我们可以从最高位开始,尝试构建最大的按位与结果。对于每一位,我们检查是否有至少两个数字在该位为1,并且这些数字在前面的高位也满足我们的构建要求。1. 算法思路
[*]从最高位(第30位)开始逐位检查
[*]尝试构建最大的按位与结果
[*]对于每一位,检查是否有至少两个数字满足当前构建的模式
[*]如果有,保留这一位;否则,跳过这一位
2. 关键点
[*]使用mask来跟踪当前构建的模式
[*]使用temp来尝试设置当前位
[*]统计满足条件的数字数量
3. 复杂度分析
[*]时间复杂度:O(32*N) ≈ O(N),非常高效
[*]空间复杂度:O(1),只使用了常数个额外变量
4. 优化点
[*]提前终止:一旦找到两个满足条件的数字就可以停止统计
[*]位运算优化:使用位运算代替乘除法
三、完整代码
#include <iostream>
#include <vector>
using namespACe std;

int findMaxAnd(vector<int>& nums) {
    int mask = 0;
    int max_and = 0;
   
    // 从最高位开始检查
    for (int i = 30; i >= 0; i--) {
      // 尝试设置这一位
      mask |= (1 << i);
      int count = 0;
      int temp = max_and | (1 << i);
      
      // 统计有多少数字包含当前构建的模式
      for (int num : nums) {
            if ((num & mask) == temp) {
                count++;
                if (count >= 2) break;
            }
      }
      
      // 如果有至少两个数字满足,保留这一位
      if (count >= 2) {
            max_and = temp;
      } else {
            mask ^= (1 << i); // 撤销这一位
      }
    }
   
    return max_and;
}

int main() {
    int N;
    cin >> N;
    vector<int> a(N);
    for (int i = 0; i < N; i++) {
      cin >> a;
    }
   
    cout << findMaxAnd(a) << endl;
    return 0;
}

来源:GESP2023年五级题烹饪问题:从暴力枚举到位运算优化深度解析
页: [1]
查看完整版本: GESP2023年五级题烹饪问题:从暴力枚举到位运算优化深度解...