zoukankan      html  css  js  c++  java
  • ZOJ 3931 Exact Compression

     题目看了半小时才看懂的。

    题意:首先根据给出的序列,构造出哈夫曼树,构造出来的是一棵二叉树,每个节点都有一个权值,每个节点的两个儿子只能取一个,问能否使取出来的节点权值之和刚好等于e。

    这样一分析就很容易看出是01背包。但是,背包容量特别大!不能纯粹的用循环做背包肯定会超时。可以使用两个队列存能够凑出来的数字(相当于滚动数组的作用),还有一个优化,看当前要压入队列的数字是否已经在队列中,这个可以用map存一下。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<algorithm>
    using namespace std;
    
    const int maxn=200;
    int s;
    long long e;
    long long f[maxn];
    struct X
    {
        long long a,b;
    } u[maxn];
    int Size,cnt;
    map<long long,bool>flag;
    
    struct cmp
    {
        bool operator ()(long long &a,long long &b)
        {
            return a>b;
        }
    };
    
    int main()
    {
        int T; scanf("%d",&T);
        while(T--)
        {
            flag.clear();
            scanf("%d",&s);
            cnt=0;
            priority_queue<long long,vector<long long>,cmp>q;
            for(int i=1; i<=s; i++)
            {
                scanf("%lld",&f[i]);
                q.push(f[i]);
            }
            scanf("%lld",&e);
            Size=s;
            while(Size!=1)
            {
                u[cnt].a=q.top();
                q.pop();
                Size--;
                u[cnt].b=q.top();
                q.pop();
                Size--;
                q.push(u[cnt].a+u[cnt].b);
                cnt++;
                Size++;
            }
    
            queue<long long>Q1;
            queue<long long>Q2;
            int f=0;
            Q1.push(u[0].a);
            Q1.push(u[0].b);
    
            for(int i=1; i<cnt; i++)
            {
                flag.clear();
                if(f==0)
                {
                    while(!Q1.empty())
                    {
                        if(Q1.front()+u[i].a<=e&&flag[Q1.front()+u[i].a]==0){
                            Q2.push(Q1.front()+u[i].a);
                            flag[Q1.front()+u[i].a]=1;
                        }
                        if(Q1.front()+u[i].b<=e&&flag[Q1.front()+u[i].b]==0){
                            Q2.push(Q1.front()+u[i].b);
                            flag[Q1.front()+u[i].b]=1;
                        }
                        Q1.pop();
                    }
                    f=1;
                }
                else
                {
                    while(!Q2.empty())
                    {
                        if(Q2.front()+u[i].a<=e&&flag[Q2.front()+u[i].a]==0){
                            Q1.push(Q2.front()+u[i].a);
                            flag[Q2.front()+u[i].a]=1;
                        }
                        if(Q2.front()+u[i].b<=e&&flag[Q2.front()+u[i].b]==0){
                            flag[Q2.front()+u[i].b]=1;
                            Q1.push(Q2.front()+u[i].b);
                        }
                        Q2.pop();
                    }
                    f=0;
                }
            }
    
            bool ans=0;
    
            if(f==0)
            {
                while(!Q1.empty())
                {
                    if(Q1.front()==e) ans=1;
                    Q1.pop();
                }
            }
            else
            {
                while(!Q2.empty())
                {
                    if(Q2.front()==e) ans=1;
                    Q2.pop();
                }
            }
    
            if(ans) printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
  • 相关阅读:
    WCF开发入门的实例
    转:SQLHelper类,泛型+反射
    设置ASP缓存的几个语句
    ADO.NET总结
    通过反射来实现:DataTable 和List 相互转换
    十步完成windows服务的安装
    dhl:The request for security token could not be satisfied because authentication failed. 调用方未由服务进行身份验证。
    C#中的readonly(运行时常量)与const(编译时常量)的区别
    用do{}创建内联子程序
    用autodie简化错误处理
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5379924.html
Copyright © 2011-2022 走看看