一:题目
对于一个以集合为元素的栈,初始时栈为空。
输入的命令有如下几种:
PUSH:将空集{}压栈
DUP:将栈顶元素复制一份压入栈中
UNION:先进行两次弹栈,将获得的集合A和B取并集,将结果压栈
INTERSECTION:先进行两次弹栈,将获得的集合A和B取交集,将结果压栈
ADD:先进行两次弹栈,将获得的集合A和B中,先出栈的集合(如A先)加入到后出栈的集合,将结果压栈
输出每一步操作后栈顶集合的元素的个数。
(一)样例输入
2
9
PUSH
DUP
ADD
PUSH
ADD
DUP
ADD
DUP
UNION
5
PUSH
PUSH
ADD
PUSH
INTERSECT
(二)样例输出
0
0
1
0
1
1
2
2
2
***
0
0
1
0
0
***
二:代码实现
(二)代码实现
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <map>
#include <vector>
#include <set>
#include <stack>
#include <string>
#include <algorithm>
using namespace std;
typedef set<int> Set;
vector<Set> Vec_Set_ID; //辅助获取集合对应ID号,其中每次只往里面添加新的集合
map<Set, int> Map_Set; //集合对应集合标识号,同上面vector,向其中添加新的集合和集合号
stack<int> Sta; //集合号栈
int GetIDForSet(Set s)
{
int number;
if (Map_Set.count(s)) //如果直接找到了编号,则直接返回集合编号
return Map_Set[s];
//若是没有找到集合标号,先将该集合放入容器中之后获取编号
Vec_Set_ID.push_back(s);
number = Vec_Set_ID.size() - 1; //重点:每个集合和其对应的编号与下标一致,方便寻找
Map_Set.insert(pair<Set, int>(s, number));
return number;
}
int main()
{
freopen("data5_5.in", "r", stdin);
freopen("data5_5.out", "w", stdout);
int count,oper_c;
string cmd;
cin >> count;
while (count--)
{
cin >> oper_c;
while (oper_c--)
{
cin >> cmd;
//开始处理
if (cmd[0] == 'P') //入空集合
Sta.push(GetIDForSet(Set()));
else if (cmd[0] == 'D') //栈顶集合复制一份入栈
Sta.push(Sta.top());
else
{
Set s;
Set s1 = Vec_Set_ID[Sta.top()]; Sta.pop();
Set s2 = Vec_Set_ID[Sta.top()]; Sta.pop();
if (cmd[0] == 'U') //出栈两个集合将其并集入栈
set_union(s1.begin(), s1.end(), s2.begin(), s2.end(), inserter(s, s.begin()));
else if (cmd[0] == 'I')
set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), inserter(s, s.begin()));
else if (cmd[0] == 'A')
{
s2.insert(GetIDForSet(s1));
s = s2;
}
//进行插入栈中
Sta.push(GetIDForSet(s));
}
//输出每一步栈顶集合的大小
cout << Vec_Set_ID[Sta.top()].size() << endl;
}
cout << "***" << endl;
}
freopen("CON", "r", stdin);
freopen("CON", "w", stdout);
return 0;
}