例题5-5集合栈计算机 UVa12096
感悟。
1、从网站下载英文原题,重点在看输入输出数据与格式。
2、借助书中中文,以为看懂了英文原题,但却怎么也推不出输出结果,傻眼了。
3、对样例2进行模拟:
PUSH {} 0
PUSH {}{} 0
ADD {{}} 1
PUSH {{}}{} 0
INTERSECT {} 0
4、对样例1进行模拟:
PUSH {} 0
DUP {}{} 0
ADD {{}} 1
PUSH {{}}{} 0
ADD {{}} 1
DUP {{}}{{}} 1
ADD {{},{{}}} 2
DUP {{},{{}}}{{},{{}}} 2
UNION {{},{{}}} 2
5、输入输出基本弄懂,也明白了集合的一个关键信息,一个集合里不会有重复元素。
6、编程感觉很奇怪,全新思路,似乎没有经验可循,无从下手。
7、不想看书中解答,本着只看提示,不看代码的原则,搜索到一篇好文http://blog.youkuaiyun.com/ACM_HKBU/article/details/44647339,核心思想如下:
这道题的思想在后面用到了几次,因此还是贴出来:
这道题是一个编码问题,即将某种数据结构通过一定的方法转化为独特的整数。这样就可以用整数来进行操作,大大简化了程序。
对于这道题中的集合来说,一个集合包含了0或多个集合,并且可能有多层嵌套,无法用STL的set来模拟。但是我们可以给每一种集合分配一个ID。比如我们给{}分配1,{{}}就可以表示成{1},我们给他分配2。{{},{}}就可以表示为{1, 1},我们给他分配3。{ {} , {{}} , {{},{}} }就可以表示为{1, 2, 3},我们可以给这个集合分配4。这样,我们就可以把集合的集合变成整数的集合,即便有再多嵌套,都可以用一个简单的整数来表示。
于是在读入操作的时候,我们判断新生成的集合是否出现过。如果出现过,直接用它对应的ID替换他。如果没出现过,则给他分配一个新的ID,并把它存在数组中ID的位置上
判断最顶部集合的大小,只需要根据ID去数组中找到这个集合,并查看这个集合中多少个元素。
8、上述思想,模模糊糊在脑中曾经掠过,但是确实没有进一步想下去,归根结底,想不到。好好学习上述思想,此题争取独立编出。
9、受到启发,编码如下:
{} 0
{{}} 1 {0}
{{},{{}}} 2 {0,1}
{{},{{}},{{},{{}}}} 3 {0,1,2}
{{},{{}},{{},{{}}},{{},{{}},{{},{{}}}}} 4 {0,1,2,3}
眼花了,顺便想起某个博客说过,只有ADD才有可能产生新的集合。
故该题难度在ADD操作。
10、编写的过程中发现,UNION也能产生新的集合。
集合元素为1的集合有很多,如9、中提到的{0},{1},{2},{3},{4},那集合为2的元素有更多了,开始觉得信息满满,马上又没思路了,不过有个好处,对该问题了解得更深了。
11、翻看书中程序,发现只是局部代码,准备开始学习新知识,靠自己想不出啊。
12、调出http://blog.youkuaiyun.com/ACM_HKBU/article/details/44647339代码,在http://vjudge.net提交AC,开始学习。
13、学习过程中,发现与本人框架有较大差异,果断换代码,调出http://blog.youkuaiyun.com/thudaliangrx/article/details/50707688代码,在http://vjudge.net提交AC,开始学习。
14、set,vector,map齐上阵,一下有点应接不暇。
15、针对13、进行测试:
输入数据:
1
19
PUSH
PUSH
PUSH
PUSH
PUSH
PUSH
PUSH
PUSH
PUSH
PUSH
ADD
ADD
ADD
ADD
ADD
ADD
ADD
ADD
ADD
输出数据:
0
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
***
上述例子每步操作结束后,vector,set,map数据跟踪:
operation 1: +++++++++++++++++
vector:
set 0 元素:
map:
key set 元素: value: 0
operation 2: +++++++++++++++++
vector:
set 0 元素:
map:
key set 元素: value: 0
operation 3: +++++++++++++++++
vector:
set 0 元素:
map:
key set 元素: value: 0
operation 4: +++++++++++++++++
vector:
set 0 元素:
map:
key set 元素: value: 0
operation 5: +++++++++++++++++
vector:
set 0 元素:
map:
key set 元素: value: 0
operation 6: +++++++++++++++++
vector:
set 0 元素:
map:
key set 元素: value: 0
operation 7: +++++++++++++++++
vector:
set 0 元素:
map:
key set 元素: value: 0
operation 8: +++++++++++++++++
vector:
set 0 元素:
map:
key set 元素: value: 0
operation 9: +++++++++++++++++
vector:
set 0 元素:
map:
key set 元素: value: 0
operation 10: +++++++++++++++++
vector:
set 0 元素:
map:
key set 元素: value: 0
operation 11: +++++++++++++++++
vector:
set 0 元素:
set 1 元素:
0
map:
key set 元素: value: 0
key set 元素: 0 value: 1
operation 12: +++++++++++++++++
vector:
set 0 元素:
set 1 元素:
0
set 2 元素:
1
map:
key set 元素: value: 0
key set 元素: 0 value: 1
key set 元素: 1 value: 2
operation 13: +++++++++++++++++
vector:
set 0 元素:
set 1 元素:
0
set 2 元素:
1
set 3 元素:
2
map:
key set 元素: value: 0
key set 元素: 0 value: 1
key set 元素: 1 value: 2
key set 元素: 2 value: 3
operation 14: +++++++++++++++++
vector:
set 0 元素:
set 1 元素:
0
set 2 元素:
1
set 3 元素:
2
set 4 元素:
3
map:
key set 元素: value: 0
key set 元素: 0 value: 1
key set 元素: 1 value: 2
key set 元素: 2 value: 3
key set 元素: 3 value: 4
operation 15: +++++++++++++++++
vector:
set 0 元素:
set 1 元素:
0
set 2 元素:
1
set 3 元素:
2
set 4 元素:
3
set 5 元素:
4
map:
key set 元素: value: 0
key set 元素: 0 value: 1
key set 元素: 1 value: 2
key set 元素: 2 value: 3
key set 元素: 3 value: 4
key set 元素: 4 value: 5
operation 16: +++++++++++++++++
vector:
set 0 元素:
set 1 元素:
0
set 2 元素:
1
set 3 元素:
2
set 4 元素:
3
set 5 元素:
4
set 6 元素:
5
map:
key set 元素: value: 0
key set 元素: 0 value: 1
key set 元素: 1 value: 2
key set 元素: 2 value: 3
key set 元素: 3 value: 4
key set 元素: 4 value: 5
key set 元素: 5 value: 6
operation 17: +++++++++++++++++
vector:
set 0 元素:
set 1 元素:
0
set 2 元素:
1
set 3 元素:
2
set 4 元素:
3
set 5 元素:
4
set 6 元素:
5
set 7 元素:
6
map:
key set 元素: value: 0
key set 元素: 0 value: 1
key set 元素: 1 value: 2
key set 元素: 2 value: 3
key set 元素: 3 value: 4
key set 元素: 4 value: 5
key set 元素: 5 value: 6
key set 元素: 6 value: 7
operation 18: +++++++++++++++++
vector:
set 0 元素:
set 1 元素:
0
set 2 元素:
1
set 3 元素:
2
set 4 元素:
3
set 5 元素:
4
set 6 元素:
5
set 7 元素:
6
set 8 元素:
7
map:
key set 元素: value: 0
key set 元素: 0 value: 1
key set 元素: 1 value: 2
key set 元素: 2 value: 3
key set 元素: 3 value: 4
key set 元素: 4 value: 5
key set 元素: 5 value: 6
key set 元素: 6 value: 7
key set 元素: 7 value: 8
operation 19: +++++++++++++++++
vector:
set 0 元素:
set 1 元素:
0
set 2 元素:
1
set 3 元素:
2
set 4 元素:
3
set 5 元素:
4
set 6 元素:
5
set 7 元素:
6
set 8 元素:
7
set 9 元素:
8
map:
key set 元素: value: 0
key set 元素: 0 value: 1
key set 元素: 1 value: 2
key set 元素: 2 value: 3
key set 元素: 3 value: 4
key set 元素: 4 value: 5
key set 元素: 5 value: 6
key set 元素: 6 value: 7
key set 元素: 7 value: 8
key set 元素: 8 value: 9
***
16、对13、中的代码进行一番捣鼓,终于弄明白了。同时也发现了switch的case下不能声明set<int> s;
17、开始编码,磕磕碰碰,实在没则,与13、中的代码进行比对,改正了错误,总算在http://vjudeg.net上WA了,提交https://uva.onlinejudge.org也AC了,看看时间2016-11-17 21:56,代码与13、略有不同,可能更适合初学者阅读。
附上AC代码,编译环境Dev-C++4.9.9.2
#include <iostream>
#include <stack>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
using namespace std;
typedef set<int> Set;
stack<int> s;
Set se;
map<Set,int> mp;
vector<Set> vec;
int getid(Set st){
if(mp.count(st))
return mp[st];
vec.push_back(st);
mp[st]=vec.size()-1;
return vec.size()-1;
}
void operate(){
string cmd;
Set s0;//空集
Set s1,s2,s3;
int id1,id2;
Set::iterator it,it2;
cin>>cmd;
switch(cmd[0]){
case 'P':
s.push(getid(s0));
break;
case 'D':
id1=s.top();
s.pop();
s.push(id1);
s.push(id1);
break;
case 'U':
id1=s.top();
s.pop();
id2=s.top();
s.pop();
s1=vec[id1];
s2=vec[id2];
for(it=s1.begin();it!=s1.end();it++)
s2.insert(*it);
s.push(getid(s2));
break;
case 'I':
id1=s.top();
s.pop();
id2=s.top();
s.pop();
s1=vec[id1];
s2=vec[id2];
for(it=s1.begin();it!=s1.end();it++)
for(it2=s2.begin();it2!=s2.end();it2++)
if(*it==*it2)//此处不是地址,应该是地址里的内容 ,写成 it==it2 就WA了
s3.insert(*it);
s.push(getid(s3));
break;
case 'A'://最难写的操作 ,相加,取什么值?
id1=s.top();
s.pop();
id2=s.top();
s.pop();
s1=vec[id1];
s2=vec[id2];
s2.insert(id1);
s.push(getid(s2));
break;
}
}
int main(){
int T;
int n;
cin>>T;
while(T--){
cin>>n;
while(n--){
operate();
cout<<vec[s.top()].size()<<endl;
}
cout<<"***"<<endl;
}
return 0;
}