12096 - The SetStack Computer

本文介绍了一种名为“集合栈”计算机的设计与实现方法,该计算机能够执行如并集、交集等集合运算,并通过栈来组织数据。文章详细解释了如何使用C++编程语言来实现这些功能,包括数据结构的选择和算法的运用。

The SetStack Computer

PS:因为该题排版较麻烦,这里给出OJ网址:UVa12096 - The SetStack Computer


有一个专门为了集合运算而设计的“集合栈”计算机。该机器有一个初始为空的栈,并且支持以下操作。

  • PUSH:空集“{}”入栈。
  • DUP:把当前栈顶元素复制一份后再入栈。
  • UNION:出栈两个集合,然后把二者的并集入栈。
  • INTERSECT:出栈两个集合,然后把二者的交集入栈。
  • ADD:出栈两个集合,然后把先出栈的集合加入到后出栈的集合中,把结果入栈。

每次操作后,输出栈顶集合的大小(即元素个数)。例如,栈顶元素是A={{},{{}}},下一个元素是B={{},{{{}}}},则:

  • UNION操作将得到{{},{{}},{{{}}}},输出3。
  • INTERSECT操作将得到{{}},输出1。
  • ADD操作将得到{{},{{{}}},{{},{{}}}},输出3。

输入不超过2000个操作,并且保证操作均能顺利进行(不需要对空栈执行出栈操作)。

#include <iostream>
#include <string>
#include <stack>
#include <set>
#include <map>
#include <vector>
#include <algorithm>

using namespace std;
// 设计思路:
// map只能获取key->value这样的关联
// 如果想通过value->key就必须再添加另一种辅助容器
// 在这是通过vector容器实现value->key,也就是说具有以下关系
// idCache[x] 为集合x的id
// setCache[idCache[x]] 就是x集合本身

// set<int>为集合,int为id
map<set<int>, int> idCache;
// 缓存set集合
vector<set<int> > setCache;

// 查找给定集合s的ID,如果未找到,分配一个新ID
int ID(set<int> s) {
    if(idCache.count(s)) {
        return idCache[s];
    }
    // 将集合x加入到set缓存中
    setCache.push_back(s);
    // 将集合x在缓存中的位置,作为唯一ID
    return idCache[s] = setCache.size() - 1;
}

int main() {
    int T;
    cin >> T;
    while(T--) {
        // 集合栈
        stack<int> s;
        int n;
        cin >> n;
        for(int i = 0; i < n; i++) {
            // 操作
            string op;
            cin >> op;
            // PUSH
            if(op[0] == 'P') {
                // 将空集入栈
                s.push(ID(set<int>()));
            } else if(op[0] == 'D') {
                // DUP
                // 将栈顶元素再次入栈
                s.push(s.top());
            } else {
                // 取出栈顶的两个元素
                set<int> x1 = setCache[s.top()];
                s.pop();
                set<int> x2 = setCache[s.top()];
                s.pop();

                set<int> x;
                // UNION
                if(op[0] == 'U') {
                    // 1,2参数为集合x1的元素开始结束位置迭代器
                    // 3,4参数为集合x2的元素开始结束位置迭代器
                    // 5参数代表插入迭代器
                    set_union(x1.begin(), x1.end(), x2.begin(), x2.end(), inserter(x, x.begin()));
                }
                // INTERSECT
                if(op[0] == 'I') {
                    set_intersection(x1.begin(), x1.end(), x2.begin(), x2.end(), inserter(x, x.begin()));
                }
                // ADD
                if(op[0] == 'A') {
                    x = x2;
                    x.insert(ID(x1));
                }
                s.push(ID(x));
            }
            cout << setCache[s.top()].size() << endl;
        }
        cout << "***" << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值