集合栈计算机(详细解答)UVa12096

题目:
有一个专门为了集合运算而设计的“集合栈”计算机。该机器有一个初始为空的栈,并且支持以下操作:
PUSH:空集“{}”入栈
DUP:把当前栈顶元素复制一份后再入栈
UNION:出栈两个集合,然后把两者的并集入栈
INTERSECT:出栈两个集合,然后把二者的交集入栈
ADD:出栈两个集合,然后把先出栈的集合加入到后出栈的集合中,把结果入栈
每次操作后,输出栈顶集合的大小(即元素个数)。例如栈顶元素是A={ {}, {{}} }, 下一个元素是B={ {}, {{{}}} },则:
UNION操作将得到{ {}, {{}}, {{{}}} },输出3.
INTERSECT操作将得到{ {} },输出1
ADD操作将得到{ {}, {{{}}}, { {}, {{}} } },输出3.
(输入:先输入测试次数,再输入操作次数,再输入具体操作)

输入:
9
PUSH
DUP
ADD
PUSH
ADD
DUP
ADD
DUP
UNION

输出:
0
0
1
0
1
1
2
2
2

解题思路:
首先注意他这个集合就是STL中的set,然后模拟,根据它的要求进行做就好了,关键是需要STL中的一些工具以及对set,map,vector的操作熟练。我把这道题要用的方法写在下面包括宏定义。
我在说一下这道题set,map,vector之间的联系。
首先定义了新数据类型Set,然后map的key值为Set,value值为在vector之中的下标,vector中存放Set元素,每次新的Set元素通过ID()方法,将Set存到vector,将对应位置存到map的value中。

题中方法:

set_union(A.begin(),A.end(),B.begin(),B.end(),inserter( C1 , C1.begin() ) );前四个参数依次是第一的集合的头尾,第二个集合的头尾。第五个参数的意思是将集合A、B取合集后的结果存入集合C中。

set_intersection()里面参数和set_union()方法相同,只不过这个是求交集。

inserter(x,x.begin),x表示容器,x.begin()表示迭代器。所以inserter()是一个迭代器返回x.begin()所指向的位置,第二个参数也可以是别的迭代器。

#define ALL(x) x.begin(),x.end() 名字为ALL传入参数x,表示从x的头到x的尾。
#define INS(x) inserter(x,x.begin()) 名字为INS,代表一个迭代器,指向x的开头。

代码:(代码中有详细注释)

#include <bits/stdc++.h>
#define ALL(x)x.begin(),x.end()
#define INS(x)inserter(x,x.begin())
using namespace std;

typedef set<int> Set;//定义新类型Set
map<Set,int> IDcache;//key位Set类型,value为Set的ID
vector<Set> Setcache;//存放Set集合的数组,通过下标ID找到Set

//ID()给传入的Set定义编号(ID)
int ID(Set x)
{
    if(IDcache.count(x))return IDcache[x];//如果map中包含x,则返回x的ID
    Setcache.push_back(x);//添加集合
    return IDcache[x]=Setcache.size()-1;//定义x的ID为vector长度减去1
}


int main()
{

    stack<int>s; //用一个栈,存放Set的ID
    int n;//n次操作
    cin>>n;
    for(int i=0;i<n;i++)
    {
        string op;//定义操作
        cin>>op;
        if(op[0]=='P')s.push(ID(Set()));//PUSH,添加空集
        else if(op[0]=='D')s.push(s.top());//DUP,将栈顶元素在添加进栈中
        else{
                //用x1,x2存放栈顶对应的Set,然后pop()出去栈顶元素
            Set x1=Setcache[s.top()];s.pop();
            Set x2=Setcache[s.top()];s.pop();
            Set x;
            if(op[0]=='U') set_union(ALL(x1),ALL(x2),INS(x));//合并集合x1,x2,存入x
            if(op[0]=='I') set_intersection(ALL(x1),ALL(x2),INS(x));//取交集存入x
            if(op[0]=='A'){x=x2;x.insert(ID(x1));}//ADD,先将x1插入x2存到x,在将x存入栈
            s.push(ID(x));
        }
        cout<<Setcache[s.top()].size()<<endl;

    }
    return 0;
}

谢谢观看!
创作不易,多多支持!嘻嘻~~~

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值