• 题目笔记 UVA12096


      一道综合set,map,stack的STL题目,非常有意思!!

    UVA12096  AC码

    #include<iostream>
    #include<map>
    #include<vector>
    #include<algorithm>
    #include<cstring>
    #include<set>
    #include<stack>
    using namespace std;
    
    int n,m;
    typedef set<int> jihe;//栈(sta)里存的都是int,而int所代表的集合里也是int
    map<jihe,int> quanzhi;
    vector<jihe>idinsetout;
    stack<int>sta;//栈(sta)里存的都是int(表示集合),因为是集合套集合所以集合里也是int(表示另一集合)
    
    
    #define ALL(x) x.begin(),x.end()
    #define INS(x) inserter(x,x.begin())
    
    int setinidout(jihe c)
    {
        if(quanzhi.count(c)) return quanzhi[c];//之前写的是:idinsetout.count(c),被绕晕了
        idinsetout.push_back(c);           //(第一次忘了这个)在vector里新加上一个
        return quanzhi[c]=idinsetout.size()-1;//他的角标就是他的权值(这两步新建集合)
    }
    
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>m;
            for(int j=1;j<=m;j++)
            {
                string s;
                cin>>s;
                if(s[0]=='P') sta.push(setinidout(jihe()));//这里jihe()
                else if(s[0]=='D') sta.push(sta.top());//stack和vector的push操作有区别
                else
                {
                    jihe a=idinsetout[sta.top()];
                    sta.pop();
                    jihe b=idinsetout[sta.top()];
                    sta.pop();
                    jihe x;
                    if(s[0]=='U') set_union (ALL(a),ALL(b),INS(x));
                    if(s[0]=='I') set_intersection (ALL(a),ALL(b),INS(x));
                    if(s[0]=='A') {x=b;x.insert(setinidout(a));}
                    sta.push(setinidout(x));
                }
                cout<<idinsetout[sta.top()].size()<<endl;
            }
            cout<<"***"<<endl;
        }
    }

    梳理

    因为第一次思路太乱了错了好几处

    所以我重打一遍来捋清思路

    (首先头文件肯定不变)

    思路

     题意是集合入栈,我们的思路是用权值代表集合,因此

    stack<int>s;

    1.给不同的集合赋不同的权值,并且可以双向导出

    但map只能导出集合的权值,所以我们需要另一个容器来导出集合

    由于该集合容器不定长,所以可以用vector

    map<set<int>,int> idout;
    vector<set<int>> lib;

    2.集合套集合,集合本身是能充当元素的(核心)

    权值代替集合所以集合的数据类型为int

    而不同权值代表的集合可以通过上面的vector得到

    typedef set<int>sEt;//这里typedef一个sEt可以简化上面两行代码
    
    map<sEt,int> Map;
    vector<sEt>lib;

     

    双向导出

    1.已知集合将其放入map中得到权值,通过函数导出&新建

    int sear (sEt a)
    {
        if(lib.count(a)) return Map[a];   库里有就直接map返回
        lib.push_back(a);                 没有就push进库
        Map[a]=lib.size()-1;              加一组map,定义vector的序号为权值
    }

    2.已知权值直接lib[序号]

    PUSH

    s.push(空集权值);

    空集权值-->sear(空集);

    s.push(sear(sEt()));   //空集入栈

    DUP

    (略)

    UNION&INTERSECT&ADD

    出栈两个集合:

    sEt a=lib[s.top()];
    s.pop();
    sEt b=lib[s.top()];
    s.pop();

    并集:   set_union( )

    交集:   set_intersection(  )

    插入:   集合.insert( )

     //这里可以用宏定义简化

    最后把集合x压入栈

    s.push(sear(x));

    框架

    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>m;
            
            for(int j=1;j<=m;j++)
            {
                string s;
                  
                cin>>s;
                
                if(s[0]=='P').             PUSH操作
               
                else if(s[0]=='D')       DUP操作
                
                else
                {
                  UNION&INTERSECT&ADD操作
                }
               
                cout<<栈顶集合大小<<endl;
            }
    
            cout<<"***"<<endl;
    
        }
    }                    
  • 相关阅读:
    MVC模式的学生信息增删改查
    常用排序算法
    2803 爱丽丝·玛格特罗依德
    3118 高精度练习之除法
    中秋练习题
    poj2011
    P1558 色板游戏
    P1830 轰炸III
    P1656 炸铁路
    1067 机器翻译
  • 原文地址:https://www.cnblogs.com/juuich/p/12392768.html
Copyright © 2020-2023  润新知