例题5-5 集合栈计算机 UVa12096

来源:互联网 发布:启用网络发现自动关闭 编辑:程序博客网 时间:2024/06/06 02:44
算法竞赛入门经典(第2版) 第5C++与STL入门

题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.csdn.net/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.csdn.net/ACM_HKBU/article/details/44647339代码,在http://vjudge.net提交AC,开始学习。

13、学习过程中,发现与本人框架有较大差异,果断换代码,调出http://blog.csdn.net/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;
}



0 0
原创粉丝点击