题目链接:Problem - 1285D - Codeforces
题目大意:就是说给你一些数x1,x2,……xn,让你找到一个数y使得y与x1,x2,……xn中任何一个数的异或值的最大值最小。
这道题目呢,我是用dfs做的,容易想到的是我们先要把这些数加入tire树中,但这与之前那个最大异或对的题目有很大不同,在那道题目中我们是要用一个确定的数去寻找最大异或值,而这道题目没有给出具体的值。但是我们可以利用贪心的思想来构造出一个数使得他满足题意,我们还是按照构建tire树的方法来遍历,只是在遍历过程中有选择性地确定搜索的方向,代码中有详细解释,下面给出代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=4e6+10;
int son[N][2],idx;
//建立tire树
void insert(int x)
{
int p=0;
for(int i=31;i>=0;i--)
{
int u=x>>i&1;
if(!son[p][u]) son[p][u]=++idx;
p=son[p][u];
}
}
//搜索构造异或最大值的最小值
int dfs(int p,int pos)
{
int ans=0;//最大异或值的最小值
if(son[p][0]&&son[p][1])//当前情况说明,无论y的第32-pos位是0还是1,异或以后这一位都会出现1
{
ans+=1<<(31-pos);//因为异或以后这一位一定是1,所以计入答案
ans+=min(dfs(son[p][0],pos+1),dfs(son[p][1],pos+1));//递归找出之后位所形成的最小值
}
else if(son[p][0])//如果当前位置就只有0,我们可以取y的当前位为1,再递归找出之后位所形成的最小值
ans+=dfs(son[p][0],pos+1);
else if(son[p][1])//如果当前位置就只有1,我们可以取y的当前位为0,再递归找出之后位所形成的最小值
ans+=dfs(son[p][1],pos+1);
return ans;
}
int main()
{
int n,t;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&t);
insert(t);
}
printf("%d",dfs(0,0));
return 0;
}