题解 The SetStack Computer(UVa12096)紫书P116STL的综合应用

先上Vjudge地址:点击这里

题目:

有一个专门为了集合运算而设计的“集合栈”计算机。该机器有一个开始为空的栈并且支持以下操作。
1.PUSH:空集“{}”入栈。
2.DUP:把当前栈顶元素复制一份后在入栈。
3.UNION:出栈两个集合,然后把二者的并集入栈。
4.INTERSECT:出栈两个集合,然后把二者的交集入栈。
5.ADD:出栈两个集合,然后把先出栈的集合加入到后出栈的集合中,把结果入栈。

例如,栈顶元素是A = { {},{{}} },下一个元素是B = { {}, {{{}}} },则:
UNION 操作将得到{ {}, {{}}, {{{}}} },输出3.
INTERSECT 操作将得到{ {} },输出1。
ADD 操作将得到{ {}, {{{}}},{{} , {{}}} },输出3。

输入:

第一行有一个整数T(0<=T<=5)表示有T组测试数据。
每组测试数据有N(0<=N<=2000)次操作,保证操作均能顺利进行(不需要对空栈执行出栈操作)。

输出:

对于输入中指定的每个操作,输出栈顶集合的大小(即元素个数)并换行。
每组测试数据后输出一行“***”。

样例:

Intput
2
9
PUSH
DUP
ADD
PUSH
ADD
DUP
ADD
DUP
UNION
5
PUSH
PUSH
ADD
PUSH
INTERSECT

Output
0
0
1
0
1
1
2
2
2
***
0
0
1
0
0
***

题目分析(依据紫书):

如何模拟题目所述的集合栈呢?大佬们满天飞的stl操作实在是令人折服;
而在本题中要单独说明的一点是,题目中的一切集合都是由一个空集进行操作得来的,故集合内元素的形式绝不仅限于括号或数字,可以延申得更为广泛;

数据结构(重中之重):
说明数据结构的选择之前,我们知道集合内的每个元素都是唯一的,如此便可以给集合内的每个元素赋予序号,在不对元素本身进行操作的情况下以序号代替元素;
例如:{{}}标以序号1,{{},{}}标以序号2,{{{}},{}}标以序号3…等等;
这样我们便可以用set a储存每个集合,
利用map,int> IDcache 储存集合和序号的对应关系;
利用vector> Setcache 来进行通过序号获取集合内容;
定义stcak s 存储集合序号的栈;

至此,我们已经可以通过定义的容器和STL的内置函数实现题目中要求的一系列操作了;

算法设计:
就硬模拟呗;

模块设计: 定义与预处理–读入与初始化–模拟–输出–return 0;

代码:

#include
using namespace std;

typedef set<int> Set;
map<Set,int> IDcache;
vector<Set> Setcache;
int t,n;

int ID(Set x){
	 if(IDcache.count(x)) return IDcache[x]; //通过map获取集合标号
	 Setcache.push_back(x);
	 return IDcache[x]=Setcache.size()-1; //查找不到就后续标号
}

#define ALL(x) x.begin(),x.end()       //蒟蒻不懂的宏,仅仅是套装用
#define INS(x) inserter(x,x.begin())

int main()
{
	 cin>>t;
	 while(t--)
	 {
	 	 stack<int> s;
	 	 cin>>n;
	 	 string order;
	 	 for(int i=0;i<n;i++)
	 	 {
	 	 	 cin>>order;
	 	 	 if(order=="PUSH") s.push(ID(Set()));
	 	 	 else if(order=="DUP") s.push(s.top());
	 	 	 else{
	 	 	 	 Set x1=Setcache[s.top()];
	 	 	 	 s.pop();
	 	 	 	 Set x2=Setcache[s.top()];
	 	 	 	 s.pop();
	 	 	 	 Set x;
	 	 	 	 if(order=="UNION") set_union (ALL(x1),ALL(x2),INS(x));
	 	 	 	 if(order=="INTERSECT") set_intersection (ALL(x1),ALL(x2),INS(x));
	 	 	 	 if(order=="ADD") { x=x2; x.insert(ID(x1));}
	 	 	 	 s.push(ID(x));
			 }
			 cout<<Setcache[s.top()].size()<<endl;
		 }
		 cout<<"***"<<endl;
	 }
	 return 0;
}

要点与细节总结:

  1. 关于代码中的set_unionset_intersection是STL的内置函数,存于头文件#include,uinon为取并集,intersection为取交集;使用详情参考这里;
  2. 膜拜大佬STL的使用;
更新与2020.7.3

你可能感兴趣的:(题解)