UVA12096 集合棧計算機(map和vector實現雙射關系+集合的交並運算的STL)


題目大意:

對於一個以集合為元素的棧,初始時棧為空。

輸入的命令有如下幾種:

PUSH:將空集{}壓棧

DUP:將棧頂元素復制一份壓入棧中

UNION:先進行兩次彈棧,將獲得的集合A和B取集,將結果壓棧

INTERSECTION:先進行兩次彈棧,將獲得的集合A和B取集,將結果壓棧

ADD:先進行兩次彈棧,將獲得的集合A和B中,先出棧的集合(如A先)加入到后出棧的集合,將結果壓棧

輸出每一步操作后棧頂集合的元素的個數。

題目詳細信息見傳送門

 

思路如下:

對於集合的集合,我們很難直接表示,因此,我們可以換一種想法,既然集合的集合難以表示,我們就只需要給每種集合一個唯一的ID就可以了,這樣,集合中的元素就可以通過ID來表示。一個集合就可以表示為一個set<int>

在這里,我們使用STL中的set進行表示,就會容易很多,加入棧中的元素也就可以是int類型了

在進行操作時,我們可以用map將每種集合與對應的ID關聯起來,這樣做既可以完成查找ID的任務,還可以同時判定是否出現了新的集合。

我們可以用vector作為存儲每種集合的cache,這樣,每當map中沒有相應的ID時,我們就向vector中加入一個set<int>元素,並將下標作為ID進行唯一的標識。

使用vector將set存儲起來的好處是,反過來我們也可以用ID查詢到對應的set,這樣,通過map和vector,我們實現了set 到ID 的雙射

最后,輸出棧頂集合的size屬性,即可。

 

代碼如下:

 1     //UVA12096 集合棧計算機 
 2     #include<cstdio>
 3     #include<iostream>
 4     #include<algorithm>//set_union等函數定義在這里 
 5     #include<vector>
 6     #include<set>
 7     #include<map>
 8     #include<stack>
 9     
10     #define ALL(x) x.begin(),x.end()
11     #define INS(x) inserter(x,x.begin()) //注意宏的括號和inserter 
12     
13     using namespace std;
14     
15     typedef set<int> Set;
16     map<Set,int> IDCache;
17     vector<Set> setCache;
18     int t,n;
19     char cmd[10];
20     int getID(Set s){
21         if(IDCache.count(s))return IDCache[s];
22         setCache.push_back(s);  //將新集合加入Setcache 
23         return IDCache[s]=setCache.size()-1;//將ID加入map ,同時返回新分配的ID值 
24     }
25     
26     int main(){
27         scanf("%d",&t);
28         while(t--){
29             scanf("%d",&n);
30 //            setCache.clear(); 
31             stack<int> s;
32             while(n--){
33                 scanf(" %s",&cmd);
34                 if(cmd[0]=='P')s.push(getID(Set()));
35                 else if(cmd[0]=='D')s.push(s.top());
36                 else{
37                     Set s1=setCache[s.top()];s.pop();
38                     Set s2=setCache[s.top()];s.pop();
39                     Set x;
40                     if(cmd[0]=='U')set_union(ALL(s1),ALL(s2),INS(x));
41                     if(cmd[0]=='I')set_intersection(ALL(s1),ALL(s2),INS(x));
42                     if(cmd[0]=='A'){ x=s2; x.insert(getID(s1)); }
43                     s.push(getID(x));
44                 }
45                 printf("%d\n",setCache[s.top()].size());
46             }
47             puts("***");
48         }
49     }

 

注意:

  第30行的setCache.clear()是必須注釋掉的,因為如果存在這一句,那么vector就會清空,但是對應的map卻沒有清空,就會出現wa的情況。

  從另一個角度說,只需要map和vector始終保持一致那么set和ID 的雙射關系就不會發生改變,此時我們就不需要將map和vector清空,因為不影響后續操作的結果。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM