Problem Description
Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?
Input
输入包含若干组测试数据,每组测试数据包含若干行。
输入的第一行是一个整数T(T < 10),表示共有T组数据。
每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。
Output
对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
对于每个询问,输出一个正整数K,使得K与S异或值最大
Sample Input
2 3 2 3 4 5 1 5 4 1 4 6 5 6 3
Sample Output
Case #1: 4 3 Case #2: 4解题思路:将给定得数按照二进制建成一颗字典树,每一层分别对应的各个位数上的01状态, 然后每一次查询,如果对应位置为0,则要往1的方向走,如果是1,则要往0的方向走。但是要注意,走的前提是对应分支是存在的。
说明:自己写的,很低级。。。
#include "stdafx.h"
#include "iostream"
#include
#include
#include
using namespace std;
#define MAX 2 //用二进制,每个节点最多有两个分支
#define maxlen pow(2,8)-1 //二进制码的长度
int *dec2Bin(int dec);//十进制转二进制
int bin2Dec(int* bin);//二进制转十进制
//定义字典树结构
struct Trie
{
Trie *next[MAX];
int v; //是否到达结尾的标志
};
Trie* createTrie(Trie *root, int *arr);//创建树
int* findTrie(Trie *root, int *arr);//查找树
int dealTrie(Trie* T);//删除树
int main()
{
int T;//数据组数
cin >> T;
int *N = new int[T];//Zeus获得数数
int *M = new int[T];//要询问的数
int** re = new int*[T];//搜索到的结果
for (int i = 0; i < T; i++)
{
Trie *tree = new Trie;
Trie *root = new Trie;
for (int m = 0;m < MAX; ++m)
{
root->next[m] = NULL;
}
cin >> N[i] >> M[i];
int *set=new int[N[i]]();
re[i] = new int[M[i]];
for (int j = 0; j < N[i]; j++)
{
cin >> set[j];
int *setBin = dec2Bin(set[j]);
tree = createTrie(root, setBin);
}
for (int k = 0; k < M[i]; k++)
{
int obj;
cin >> obj;
int *binObj = dec2Bin(obj);
int* tmp = findTrie(tree, binObj);
re[i][k] = bin2Dec(tmp);
}
dealTrie(tree);
}
for (int i = 0; i < T; i++)
{
cout << "Case #" << i + 1 << ":" << endl;
for (int j = 0; j < M[i]; j++)
{
cout << re[i][j] << endl;
}
}
system("pause");
return 0;
}
Trie* createTrie(Trie *root, int *arr)
{
int len = maxlen;
Trie *p = root; Trie *q = new Trie;
for (int i = 0; inext[id] == NULL)
{
q = (Trie *)malloc(sizeof(Trie));
q->v = 1;
for (int j = 0; jnext[j] = NULL;
p->next[id] = q;
p = p->next[id];
}
else
{
//p->next[id]->v++;
p = p->next[id];
}
}
p->v = -1; //若为结尾,则将v改成-1表示
return root;
}
int* findTrie(Trie *root, int *arr)
{
Trie *p = root;
int len = maxlen;
int* re = new int[len]();
for (int i = 0; i < len; i++)
{
int id = arr[i];
if (p->next[1 - id] != NULL)//优先选择与要查询的数这一位相反的方向
{
re[i] = 1 - id;
p = p->next[1 - id];
}
else
{
p = p->next[id];
re[i] = id;
}
}
return re;
}
int dealTrie(Trie* T)
{
int i;
if (T == NULL)
return 0;
for (i = 0; i < MAX; i++)
{
if (T->next[i] != NULL)
dealTrie(T->next[i]);
}
free(T);
return 0;
}
int* dec2Bin(int dec)
{
int len = maxlen;
int *b = new int[len]();;
int i = dec;
int j = 1;
while (i)
{
b[len-j] = i % 2;
i = i / 2;
j++;
}
return b;
}
int bin2Dec(int* bin)
{
int len = maxlen;
int re=0;
for (int i = 0; i < len; i++)
{
re += pow(2, len - 1 - i)*bin[i];
}
return re;
}
另外把给出的答案记录一下:
觉得大神写的太巧妙了,,,
#include "stdafx.h"
#include
#include
#include
using namespace std;
//typedef __int64 ll;
typedef long long ll;
const int M = 55;
const int N = M*1e5;
struct Node {
ll val;
int l;
int r;
void clear() {
l = r = -1;
}
}node[N];
int p;
ll a, t[M];
void insert(int& root, int d, ll u) {//尤其注意这里的按引用调用!!!root值改变的话,node[root].l的值也改变了!!!!,并且递归到底后root=51后,要逐层返回,最后root为0
if (root == -1) {
root = p++;
node[root].clear();
}
if (d == -1) {
node[root].val = u;
return;
}
if (u & t[d])
insert(node[root].r, d - 1, u);
else
insert(node[root].l, d - 1, u);
}
void query(int root, int d, ll u) {
if (d == -1) {
printf("%lld\n", node[root].val);
return;
}
if (((u & t[d]) && node[root].l != -1) || node[root].r == -1)
query(node[root].l, d - 1, u);
else
query(node[root].r, d - 1, u);
}
int main() {
//cout << sizeof(unsigned int);
int cas, n, m;
scanf("%d", &cas);
t[0] = 1;
for (int i = 1; i < 55; i++)
t[i] = t[i - 1] * 2;
for (int i = 1; i <= cas; i++) {
p = 0;
int root = -1;
scanf("%d%d", &n, &m);
for (int j = 0; j < n; j++) {
scanf("%lld", &a);
insert(root, 50, a);
}
printf("Case #%d:\n", i);
for (int j = 0; j < m; j++) {
scanf("%lld", &a);
query(root, 50, a);
}
}
return 0;
}