一个FLAG #14# The SetStack Computer

集合栈计算机,完整题目见参考[1]

书上的原始代码如下:

#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <stack>
#include <algorithm>
// algorithm是必要的?否则 set_union报错 

using namespace std;

typedef set<int> Set;
map<Set, int> ID_cache;
vector<Set> Set_cache;

// 查找指定集合的 id 如果找不到,分配一个新的 
int ID(Set x) {
    if (ID_cache.count(x)) {
        return ID_cache[x]; // 返回相应 ID 
    } else {
        Set_cache.push_back(x); // 把集合放入集合cache中 
        return ID_cache[x] = Set_cache.size() - 1; 
        // 新分配ID也就是新集合在集合cache中的位置 
        // Set_cache[id] 就是那个对应的集合 
    }
}

#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x.begin())

int main()
{
    stack<int> s; // 方便起见,为每个不同的集合,分配一个唯一的ID 
    
    int n;
    cin >> n;
    for (int i = 0; i != n; ++i) {
        string op;
        cin >> op;
        if (op[0] == 'P') {
            s.push(ID(Set()));
            // PUSH操作 空集{}入栈
            // 这里实际是创建了一个空的 set<int> 对象
            // 然后将其添加到 set_cache中 并分配了一个唯一的id
            // 通过 set_cache[id] 可以拿到这个集合,通过 IDcache[这个集合] 可以拿到它的id  
            // 通过ID()函数封装了这些操作。然后用id来充当集合进行操作 
        } else if (op[0] == 'D') {
            s.push(s.top());
            // DUP操作
            // 只是把一个数字push进去。集合本身没有拷贝
            // DUP多次的结果就是,栈中会有多个数字指向一个集合 
        } else {
            // UNION 以及 INTERSECT 以及 ADD操作首先都需要出栈两个集合
            Set x1 = Set_cache[s.top()]; // setcache中的集合是永不消除的 
            s.pop();
            Set x2 = Set_cache[s.top()];
            s.pop();
            Set x;
            if (op[0] == 'U') {
                // 求并集 
                set_union(ALL(x1), ALL(x2), INS(x));
            }
            if (op[0] == 'I') {
                set_intersection(ALL(x1), ALL(x2), INS(x));        
            }
            if (op[0] == 'A') {
                x = x2;
                x.insert(ID(x1)); 
                // 所以这个集合也是插入数字 并没有真正把集合插入到集合里去 
                // 所以是用 set<int> 就可以 
            }
            s.push(ID(x));
        }
        cout << Set_cache[s.top()].size() << endl;
    }    
}

改了一下变量名,感觉还是没有很清晰。

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

using namespace std;

typedef set<int> MySet;
map<MySet, int> ids; 
vector<MySet> sets;  

int getId(MySet mySet) {
    if (ids.count(mySet)) {
        return ids[mySet];
    } else {
        sets.push_back(mySet);
        return ids[mySet] = sets.size() - 1; 
    }
}

MySet getMySet(int id) {
    return sets[id];
}

#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x.begin())

int main()
{
    stack<int> stack;
    
    int n;
    cin >> n;
    for (int i = 0; i != n; ++i) {
        string op;
        cin >> op;
        if (op[0] == 'P') {
            stack.push(getId(MySet()));
        } else if (op[0] == 'D') {
            stack.push(stack.top());
        } else {
            MySet set1 = getMySet(stack.top()); 
            stack.pop();
            MySet set2 = getMySet(stack.top());
            stack.pop();
            MySet set;
            if (op[0] == 'U') {
                set_union(ALL(set1), ALL(set2), INS(set));
            }
            if (op[0] == 'I') {
                set_intersection(ALL(set1), ALL(set2), INS(set));        
            }
            if (op[0] == 'A') {
                set = set2;
                set.insert(getId(set1)); 
            }
            stack.push(getId(set));
        }
        cout << getMySet(stack.top()).size() << endl;
    }    
}

参考

[1] https://vjudge.net/problem/UVA-12096

原文地址:https://www.cnblogs.com/xkxf/p/12680031.html