首页 > ACM题库 > HDU-杭电 > hdu 1968 The SetStack Computer-栈-[解题报告]C++
2013
12-26

hdu 1968 The SetStack Computer-栈-[解题报告]C++

The SetStack Computer

问题描述 :

Background from Wikipedia: �et theory is a branch of mathematics created principally by the German mathematician Georg Cantor at the end of the 19th century. Initially controversial, set theory has come to play the role of a foundational theory in modern mathematics, in the sense of a theory invoked to justify assumptions made inmathematics concerning the existence of mathematical objects (such as numbers or functions) and their properties. Formal versions of set theory also have a foundational role to play as specifying a theoretical ideal of mathematical rigor in proofs.?Given this importance of sets, being the basis of mathematics, a set of eccentric theorist set off to construct a supercomputer operating on sets instead of numbers. The initial Set-Stack Alpha is under construction, and they need you to simulate it in order to verify the operation of the prototype.

The computer operates on a single stack of sets, which is initially empty. After each operation, the cardinality of the topmost set on the stack is output. The cardinality of a set S is denoted |S| and is the number of elements in S. The instruction set of the SetStack Alpha is PUSH, DUP, UNION, INTERSECT, and ADD.
?PUSH will push the empty set {} on the stack.
?DUP will duplicate the topmost set (pop the stack, and then push that set on the stack twice).
?UNION will pop the stack twice and then push the union of the two sets on the stack.
?INTERSECT will pop the stack twice and then push the intersection of the two sets on the stack.
?ADD will pop the stack twice, add the first set to the second one, and then push the resulting set on the stack.
For illustration purposes, assume that the topmost element of the stack is A = {{}, {{}}} and that the next one is B = {{}, {{{}}}}.
For these sets, we have |A| = 2 and |B| = 2. Then:
?UNION would result in the set { {}, {{}}, {{{}}} }. The output is 3.
?INTERSECT would result in the set { {} }. The output is 1.
?ADD would result in the set { {}, {{{}}}, {{},{{}}} }. The output is 3.

输入:

An integer 0 <= T <= 5 on the first line gives the cardinality of the set of test cases. The first line of each test case contains the number of operations 0 <= N <= 2 000. Then follow N lines each containing one of the five commands. It is guaranteed that the SetStack computer can execute all the commands in the sequence without ever popping an empty stack.

输出:

An integer 0 <= T <= 5 on the first line gives the cardinality of the set of test cases. The first line of each test case contains the number of operations 0 <= N <= 2 000. Then follow N lines each containing one of the five commands. It is guaranteed that the SetStack computer can execute all the commands in the sequence without ever popping an empty stack.

样例输入:

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

样例输出:

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

点击打开链接uva 12096

思路: STL模拟
分析:
1 题目给定5种操作,每次输出栈顶集合的元素的个数
2 利用stack和set来模拟,set保存集合的元素。遇到push的时候直接在stack里面push入一个空的set,遇到Dup的时候把栈顶的集合在push进stack一次,遇到union的时候把栈顶的两个集合合并,遇到Intersect的时候把栈顶的两个集合进行求交集然后push进stack,遇到Add的时候要注意如果第一个集合是空集那么我们就认为是在第二个集合里面加入2,否则就要通过map来判断当前的集合所表示的值

代码:

#include<set>
#include<map>
#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 20;
const int MAXN = 2010;

int cnt;
stack<set<int> >stk;
map<set<int> , int>mp;
set<int>s1 , s2;

void pop(){
    s1 = stk.top();
    stk.pop();
    
    s2 = stk.top();
    stk.pop();
}
// push
void Push(){
    set<int>s;
    stk.push(s);
    puts("0");
}
// dup 
void Dup(){
    set<int>s;
    s = stk.top();
    stk.push(s);
    printf("%d\n" , s.size());
}
// union 
void Union(){
    pop();
    // 
    set<int>::iterator it;
    for(it = s1.begin() ; it != s1.end() ; it++)
        s2.insert(*it);
    stk.push(s2);
    printf("%d\n" , s2.size());
}
// Intersect
void Intersect(){
    pop();
    //
    set<int>s3;
    set<int>::iterator it;
    for(it = s1.begin() ; it != s1.end() ; it++){
        if(s2.find(*it) != s2.end())   
            s3.insert(*it); 
    }
    stk.push(s3);
    printf("%d\n" , s3.size());
}
// add
void Add(){
    pop();
    //
    if(s1.empty())
        s2.insert(0); 
    else{
        if(!mp[s1])
            mp[s1] = cnt++;
        s2.insert(cnt++);
    }
    stk.push(s2);
    printf("%d\n" , s2.size());
}

int main(){
    int Case , n;
    char str[N];
    scanf("%d" , &Case);
    while(Case--){
        scanf("%d" , &n); 
        while(!stk.empty())
            stk.pop();
        cnt = MAXN;
        mp.clear();
        while(n--){
            scanf("%s" , str); 
            if(str[0] == 'P')
                Push();
            else if(str[0] == 'D')
                Dup();
            else if(str[0] == 'U')
                Union();
            else if(str[0] == 'I')
                Intersect();
            else
                Add();
        } 
        puts("***");
    }
    return 0;
}

解题转自:http://blog.csdn.net/chenguolinblog/article/details/9746831


  1. 题本身没错,但是HDOJ放题目的时候,前面有个题目解释了什么是XXX定律。
    这里直接放了这个题目,肯定没几个人明白是干啥

  2. #!/usr/bin/env python
    def cou(n):
    arr =
    i = 1
    while(i<n):
    arr.append(arr[i-1]+selfcount(i))
    i+=1
    return arr[n-1]

    def selfcount(n):
    count = 0
    while(n):
    if n%10 == 1:
    count += 1
    n /= 10
    return count

  3. 这道题目虽然简单,但是小编做的很到位,应该会给很多人启发吧!对于面试当中不给开辟额外空间的问题不是绝对的,实际上至少是允许少数变量存在的。之前遇到相似的问题也是恍然大悟,今天看到小编这篇文章相见恨晚。

  4. int half(int *array,int len,int key)
    {
    int l=0,r=len;
    while(l<r)
    {
    int m=(l+r)>>1;
    if(key>array )l=m+1;
    else if(key<array )r=m;
    else return m;
    }
    return -1;
    }
    这种就能避免一些Bug
    l,m,r
    左边是l,m;右边就是m+1,r;

  5. 思路二可以用一个长度为k的队列来实现,入队后判断下队尾元素的next指针是否为空,若为空,则出队指针即为所求。

  6. 第二种想法,我想来好久,为啥需要一个newhead,发现是把最后一个节点一直返回到嘴上面这层函数。厉害,这道题之前没样子想过。