两个数组最小的异或值之和
1. 状态压缩 + 动态规划
顺序不重要,依次枚举数组1的每个数,和数组2进行组合计算
class Solution {
public:
int minimumXORSum(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size();
if(judge(nums1)||judge(nums2)){
int res = 0;
for(int i=0;i<n;i++)
res = res + (nums1[i]^nums2[i]);
return res;
}
vector<int> dp(1<<n,INT_MAX);//dp[i]表示i状态下的最小亦或和
dp[0] = 0;//初始状态亦或和为0
for(int i=0;i<n;i++){//依次遍历数组1中的数,加入到状态中
for(int mask=0;mask<(1<<n);mask++){//遍历所有状态
if(__builtin_popcount(mask)==i){//从小到大
for(int j=0;j<n;j++){ //尝试给数组2中每一个数进行亦或
int state = mask|(1<<j);
if(state==mask) continue;
dp[state] = min(dp[state],dp[mask]+ (nums1[i]^nums2[j]));
}
}
}
}
return dp[(1<<n)-1];
}
bool judge(vector<int>& nums){
for(int i=1;i<nums.size();i++)
if(nums[i]!=nums[i-1]) return false;//表示不全相同
return true;
}
};
2. 更简洁的写法
class Solution {
public:
int minimumXORSum(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size();
vector<int> f(1 << n, INT_MAX);
f[0] = 0;
for (int mask = 1; mask < (1 << n); ++mask) {//枚举数组2的所有状态
for (int i = 0; i < n; ++i) {
if (mask & (1 << i)) {
//删除每个元素的状态必然是已经枚举过的状态,为前面最优,满足无后效性
f[mask] = min(f[mask], f[mask ^ (1 << i)] + (nums1[__builtin_popcount(mask) - 1] ^ nums2[i]));
}
}
}
return f[(1 << n) - 1];
}
};