UVA12096 - The SetStack Computer(set + map映射)

UVA12096 - The SetStack Computer(set + map映射)

题目链接

题目大意:有五个动作:
push : 把一个空集合{}放到栈顶。
dup : 把栈顶的集合取出来,在入栈两次。
add : 出栈两次,把第一个集合作为一个元素放入第二个集合中,再将第二个集合入栈
union: 出栈两次,取这两个集合的并集,将结果入栈。
intersect: 出栈两次,取这两个集合的交集,将结果入栈。
每次执行动作后还需要输出目前栈顶集合的元素个数。

解题思路:这题可以用栈和set来模拟,push就把空的集合入栈,但是在并集和交集的时候就需要判段集合是否相同,所以这里可以用map把出现过的集合手动的映射成数字。

代码:

#include <cstdio>
#include <cstring>
#include <stack>
#include <set>
#include <map>

using namespace std;

char op[15];
int n;

typedef set<int> E;
stack<E> s;
map<E, int> vis;
E tmp1, tmp2;
set<int>::iterator it;
int num;

void hash (E a) {

    if (!vis.count(a))
        vis[a] = ++num;
}

void Push () {

    tmp1.clear();
    s.push (tmp1);            
}

void Dup () {

    tmp1 = s.top();
    s.push (tmp1);
}

void Add () {

    tmp2 = s.top();
    s.pop();
    tmp1 = s.top();
    s.pop();
    tmp1.insert (vis[tmp2]);
    hash(tmp1);
    s.push(tmp1);
}

void Union () {

    tmp2 = s.top();    
    s.pop();
    tmp1 = s.top();
    s.pop();
    for (it = tmp1.begin(); it != tmp1.end(); it++)
        tmp2.insert (*it);
    hash (tmp2);
    s.push (tmp2);    
}

void Intersect () {

    tmp2 = s.top();
    s.pop();
    tmp1 = s.top();
    s.pop();
    E tmp;
    for (it = tmp1.begin(); it != tmp1.end(); it++)
        if (tmp2.count(*it))
            tmp.insert (*it);
    hash (tmp);
    s.push(tmp);
}

void solve () {

    switch (op[0]) {

        case 'P' : Push();     break;
        case 'D' : Dup();      break;
        case 'U' : Union();    break;
        case 'I' : Intersect(); break;
        case 'A' : Add();      break;
    }
    printf ("%d\n", s.top().size()); 
}

void init () {

    num = 1;
    while (!s.empty()) {
        s.pop();
    }
    vis.clear();
}

int main () {

    int T;
    scanf ("%d", &T);
    while (T--) {

        scanf ("%d", &n);
        while (n--) {
            scanf ("%s", op);
            solve();                
        }
        printf ("***\n");
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值