算法竞赛入门经典 例题5-5

UVa12096

The SetStack Computer

这题理解起来有一些复杂,即使理解了一时也可能想不出来该怎么表示集合套集合的情况,后来看了看书,说用整数代表每一个集合。比如题目中的例子,可以定义A={0, 1},然后A2表示,同样B={0, 3},然后B4表示,AB的并集中元素为{0, 1, 3},然后这个集合用5表示,AB的交集中元素为{0},这个集合用6表示,A + B中元素为{0, 3, 2},这个集合用7表示。

书上不仅定义了一个编号到集合的映射,而且定义了一个集合到编号的映射。最开始的时候我只定义了编号到集合的映射vecsetNum2Set,然后每做一次UNION、INTERSECT和ADD就添加一个新的编号到集合的映射关系,而不管是否和已有的重复,后来才发现这就无法保证元素的唯一性了。

#include <iostream>
#include <vector>
#include <set>
#include <string>

using namespace std;

void push(vector<int> &viStack, vector<set<int>> &vecsetNum2Set)
{
	viStack.push_back(0);
	if (vecsetNum2Set.size() <= 0) vecsetNum2Set.push_back(set<int>());
}

void dup(vector<int> &viStack, vector<set<int>> &vecsetNum2Set)
{
	viStack.push_back(viStack.back());
}

void unionset(vector<int> &viStack, vector<set<int>> &vecsetNum2Set)
{
	int top = viStack.back();
	viStack.pop_back();
	int sec = viStack.back();
	viStack.pop_back();
	set<int> si = vecsetNum2Set[top];
	for (auto iter = vecsetNum2Set[sec].begin(); iter != vecsetNum2Set[sec].end(); iter++)
	{
		si.insert(*iter);
	}
	for (size_t idx = 0; idx < vecsetNum2Set.size(); idx++)
	{
		if (vecsetNum2Set[idx] == si){
			viStack.push_back(idx);
			return;
		}
	}
	viStack.push_back(vecsetNum2Set.size());
	vecsetNum2Set.push_back(si);
}

void intersect(vector<int> &viStack, vector<set<int>> &vecsetNum2Set)
{
	int top = viStack.back();
	viStack.pop_back();
	int sec = viStack.back();
	viStack.pop_back();
	set<int> &siTop = vecsetNum2Set[top], si;
	for (auto iter = siTop.begin(); iter != siTop.end(); iter++)
	{
		if (vecsetNum2Set[sec].find(*iter) != vecsetNum2Set[sec].end()){
			si.insert(*iter);
		}
	}
	for (size_t idx = 0; idx < vecsetNum2Set.size(); idx++)
	{
		if (vecsetNum2Set[idx] == si){
			viStack.push_back(idx);
			return;
		}
	}
	viStack.push_back(vecsetNum2Set.size());
	vecsetNum2Set.push_back(si);
}

void add(vector<int> &viStack, vector<set<int>> &vecsetNum2Set)
{
	int top = viStack.back();
	viStack.pop_back();
	int sec = viStack.back();
	viStack.pop_back();
	set<int> si = vecsetNum2Set[sec];
	si.insert(top);
	for (size_t idx = 0; idx < vecsetNum2Set.size(); idx++)
	{
		if (vecsetNum2Set[idx] == si){
			viStack.push_back(idx);
			return;
		}
	}
	viStack.push_back(vecsetNum2Set.size());
	vecsetNum2Set.push_back(si);
}

int main()
{
	int T = 0, ops = 0;
	cin >> T;
	for (int t = 0; t < T; t++)
	{
		cin >> ops;
		string strOp;
		vector<int> viStack;
		vector<set<int>> vecsetNum2Set;
		for (int i = 0; i < ops; i++)
		{
			cin >> strOp;
			if (strOp == "PUSH"){
				push(viStack, vecsetNum2Set);
			}
			else if (strOp == "DUP"){
				dup(viStack, vecsetNum2Set);
			}
			else if (strOp == "UNION"){
				unionset(viStack, vecsetNum2Set);
			}
			else if (strOp == "INTERSECT"){
				intersect(viStack, vecsetNum2Set);
			}
			else if (strOp == "ADD"){
				add(viStack, vecsetNum2Set);
			}
			cout << vecsetNum2Set[viStack.back()].size() << endl;
		}
		cout << "***" << endl;
		//if (t == 42) return 0;
	}
	return 0;
}
/*
2
9
PUSH
DUP
ADD
PUSH
ADD
DUP
ADD
DUP
UNION
5
PUSH
PUSH
ADD
PUSH
INTERSECT
*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值