集合栈计算机(The Set Stack Computer,ACM/ICPC NWERC 2006,UVa12096)

集合栈计算机(The Set Stack Computer,ACM/ICPC NWERC 2006,UVa12096)

对于集合的集合,很难直接表示,因此,为方便起见,为每个不同的集合分配一个不同的ID,每个集合都可以表示成所含集合的ID集合,一个集合就可以表示为一个set

我的理解:
{}:1    {{}} 2 
栈中的都是集合,所以也是int类型的

实际进行操作的过程中,可以用map将每种集合和对应的ID关联起来,这样做既可以完成查找ID的任务,还可以同时判定是否出现了新的集合。
用vector作为存储每种集合的cache,这样,每当map中没有相应的ID时,我们就向vector中加入一个set 元素,并将下标作为ID进行唯一的标识。
使用vector将set存储起来的好处是,反过来我们也可以用ID查询到对应的set,这样,通过map和vector,我们实现了set 到ID 的双射。

//聚合栈计算机
#include
#include
#include
#include
#include
#include
#include
using namespace std;

typedef set Set;
map IDcache;
vectorSetcache;
int ID(Set x)
{
	if(IDcache.count(x)) return IDcache[x];   //map中已有key(x),返回对应的value值
	Setcache.push_back(x); //map中没有key(x),将其插入vector 中
	return IDcache[x]=Setcache.size()-1;  //将key(x)存入map中,并将对应的value赋值为在vector中的下标
}
int main()
{
	int n,k;
	stack s;
	cin>>n;
	while(n--)
	{
		cin>>k;
		while(k--)
		{
			string str;
			cin>>str;
			if(str[0]=='P') s.push(ID(set())); //空集入栈
			else if(str[0]='D') s.push(s.top());  //把当前栈顶元素复制一份后再入栈
			//剩下的三种操作,涉及到ID
			else
			{
				Set x1 = Setcache[s.top()]; s.pop();  //栈顶第一个集合   (注意:s.top()是一个id)
				Set x2 = Setcache[s.top()]; s.pop();  //第二个 
				Set x;   //有一个取并,交的新的集合 
				
				if (str[0] == 'U') set_union(x1.begin(), x1.end(), x2.begin(), x2.end(), inserter(x, x.begin()));
				if (str[0] == 'I') set_intersection(x1.begin(), x1.end(), x2.begin(), x2.end(), inserter(x, x.begin()));
				if (str[0] == 'A') { x = x2; x.insert(ID(x1)); }  //将x1的ID插入到x中
				s.push(ID(x));  //合并后的x存入vector中,再将ID压入栈中
			}
			cout << Setcache[s.top()].size() << endl;  
		}
	}
	return 0; 
}

你可能感兴趣的:(集合栈计算机(The Set Stack Computer,ACM/ICPC NWERC 2006,UVa12096))