HDU 5536 Chip Factory(暴力/Trie树)

Chip Factory

Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3288    Accepted Submission(s): 1424


Problem Description
John is a manager of a CPU chip factory, the factory produces lots of chips everyday. To manage large amounts of products, every processor has a serial number. More specifically, the factory produces  n  chips today, the  i -th chip produced this day has a serial number  si .

At the end of the day, he packages all the chips produced this day, and send it to wholesalers. More specially, he writes a checksum number on the package, this checksum is defined as below:
maxi,j,k(si+sj)sk

which  i,j,k  are three  different integers between  1  and  n . And   is symbol of bitwise XOR.

Can you help John calculate the checksum number of today?
 

Input
The first line of input contains an integer  T  indicating the total number of test cases.

The first line of each test case is an integer  n , indicating the number of chips produced today. The next line has  n  integers  s1,s2,..,sn , separated with single space, indicating serial number of each chip.

1T1000
3n1000
0si109
There are at most  10  testcases with  n>100
 

Output
For each test case, please output an integer indicating the checksum number in a line.
 

Sample Input
   
   
2 3 1 2 3 3 100 200 300
 

Sample Output
   
   
6 400
 

Source


【思路】
这道题的时限是9s,很长,暴力做法无需多言。如果时限再卡小的话,就应该用01字典树了。因为还不熟练,所以用两个思路写了两遍字典树,重点在于如何避免i、j与k重复
思路一:每一个节点用一个数组记录插入过程中经过这个节点的数的下标,查询的时候应该首先保证节点中有下标异于所枚举的两个下标,再向下访问。由于检验的过程也是暴力,所以效率不高。
思路二:每一个节点记录有多少节点在插入的过程中经过这个节点,枚举i、j先进行删除以避免和k重复,再查询a[i]+a[j]就可以了,于是就变成了经典的01字典树。

【代码1】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN=1005;

int t,n;
int a[MAXN];

int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        int ans=0;
        for(int i=1;i<=n-2;i++)
            for(int j=i+1;j<=n-1;j++)
                for(int k=j+1;k<=n;k++){
                    ans=max(ans,(a[i]+a[j])^a[k]);
                    ans=max(ans,(a[i]+a[k])^a[j]);
                    ans=max(ans,(a[j]+a[k])^a[i]);
                }
        printf("%d\n",ans);
    }
    return 0;
}

【代码2】
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

const int MAXN=1005,SIZE=2;

struct trie{
    int cnt;
    int v[MAXN];
    trie *child[SIZE];
    trie()
    {
        memset(v,0,sizeof(v));
        memset(child,NULL,sizeof(child));
        cnt=0;
    }
};

int t,n;
int a[MAXN];
trie *root;

void insert(int k)
{
    trie *p=root;
    for(int i=30;i>=0;i--){
        int id=a[k]>>i&1;
        if(p->child[id]==NULL)
            p->child[id]=new trie();
        p->child[id]->v[++(p->child[id]->cnt)]=k;
        p=p->child[id];
    }
}

bool ok(int v[],int cnt,int i,int j)
{
    for(int index=1;index<=cnt;index++)
        if(v[index]!=i&&v[index]!=j)
            return true;
    return false;
}

int query(int x,int y)
{
    int sum=a[x]+a[y],ans=0;
    trie *p=root;
    for(int i=30;i>=0;i--){
        int id=sum>>i&1;
        if(p->child[id^1]!=NULL&&ok(p->child[id^1]->v,p->child[id^1]->cnt,x,y)){
            id^=1;
            ans+=(1<<i);

        }
        p=p->child[id];
    }
    return ans;
}

void del(trie *root)
{
    for(int i=0;i<SIZE;i++)
        if(root->child[i]!=NULL)
            del(root->child[i]);
    delete(root);
}

int main()
{
    scanf("%d",&t);
    for(int kase=1;kase<=t;kase++){
        root=new trie();
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            insert(i);
        }
        int ans=0;
        for(int i=1;i<=n-1;i++)
            for(int j=i+1;j<=n;j++)
                ans=max(ans,query(i,j));
        printf("%d\n",ans);
        del(root);
    }
    return 0;
}


【代码3】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN=1005,SIZE=2;

struct trie{
    int cnt;
    trie *child[SIZE];
    trie()
    {
        memset(child,NULL,sizeof(child));
        cnt=0;
    }
};

int t,n;
int a[MAXN];
trie *root;

void insert(int x)
{
    trie *p=root;
    p->cnt++;
    for(int i=30;i>=0;i--){
        int id=x>>i&1;
        if(p->child[id]==NULL)
            p->child[id]=new trie();
        p->child[id]->cnt++;
        p=p->child[id];
    }
}

void remove(int x)
{
    trie *p=root;
    p->cnt--;
    for(int i=30;i>=0;i--){
        int id=x>>i&1;
        p->child[id]->cnt--;
        p=p->child[id];
    }
}

int query(int x)
{
    int ans=0;
    trie *p=root;
    for(int i=30;i>=0;i--){
        int id=x>>i&1;
        if(p->child[id^1]!=NULL&&p->child[id^1]->cnt>0){
            id^=1;
            ans+=(1<<i);
        }
        p=p->child[id];
    }
    return ans;
}

void del(trie *root)
{
    for(int i=0;i<SIZE;i++)
        if(root->child[i]!=NULL)
            del(root->child[i]);
    delete(root);
}

int main()
{
    scanf("%d",&t);
    for(int kase=1;kase<=t;kase++){
        root=new trie();
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            insert(a[i]);
        }
        int ans=0;
        for(int i=1;i<=n-1;i++)
            for(int j=i+1;j<=n;j++){
                int num=a[i]+a[j];
                remove(a[i]);
                remove(a[j]);
                ans=max(ans,query(num));
                insert(a[i]);
                insert(a[j]);
            }
        printf("%d\n",ans);
        del(root);
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值