木块问题 The Blocks Problem, UVa 101
描述
从左到右有n个木块,编号为0~n-1的木块,要求模拟以下4种操作(下面的a和b都是木块编号):
1、move a onto b:把木块a、b上的木块放回各自的原位,再把a放到b上;
2、move a over b:把a上的木块放回各自的原位,再把a放到含b的堆上;
3、pile a onto b:把b上的木块放回各自的原位,再把a连同a上的木块移到b上;
4、pile a over b:把a连同a上木块移到含b的堆上。
当输入quit时,结束操作并输出0~n-1的位置上的木块列表,按照从底部到顶部的顺序排列。(a和b在同一堆的指令是非法指令,应当忽略)
分析
每个木块的高度不确定,所以用vector来保存很合适;而木块堆的个数不超过n,所以用一个数组来存就可以了。
提出指令中的共同点,编写函数以减少重复代码。
move a onto b | a上的木块放回各自的原位 | b上的木块放回各自的原位 | a连同a上木块移到含b的堆上 |
move a over b | a上的木块放回各自的原位 | a连同a上木块移到含b的堆上 | |
pile a onto b | b上的木块放回各自的原位 | a连同a上木块移到含b的堆上 | |
pile a over b | a连同a上木块移到含b的堆上 |
样例
Sample Input / 输入样例 | Sample Output / 输出样例 |
10 move 9 onto 1 move 8 over 1 move 7 over 1 move 6 over 1 pile 8 over 6 pile 8 over 5 move 2 over 1 move 4 over 9 quit |
0: 0 1: 1 9 2 4 2: 3: 3 4: 5: 5 8 7 6 6: 7: 8: 9: |
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 5 using namespace std; 6 7 const int maxn = 30; 8 int n; 9 vector<int> pile[maxn]; //每个pile[i]是一个vector 10 11 //找到木块a所在的pile和height,以引用的形式返回调用者 12 void find_block(int a, int& p, int& h) 13 { 14 for(p = 0; p < n; p++) 15 { 16 for(h = 0; h < pile[p].size(); h++) 17 { 18 if(pile[p][h] == a) 19 return; 20 } 21 } 22 } 23 24 //把第p堆高度为h的木块上方的所有木块移回原位 25 void clear_above(int p, int h) 26 { 27 for(int i = h+1; i < pile[p].size(); i++) 28 { 29 int m = pile[p][i]; 30 pile[m].push_back(m); //向pile[m]尾部添加元素,把木块m放回原处 31 } 32 pile[p].resize(h+1); //改变数组大小,pile[p]只保留下标0~h的元素 33 } 34 35 //把第p堆高度为h及其上方的木块整体移动到p2堆的顶部 36 void pile_onto(int p, int h, int p2) 37 { 38 for(int i = h; i < pile[p].size(); i++) 39 pile[p2].push_back(pile[p][i]); 40 pile[p].resize(h); 41 } 42 43 void print() 44 { 45 for (int i = 0; i < n; i++) 46 { 47 cout << i << ":"; 48 for (int j = 0; j < pile[i].size(); j++) 49 cout << pile[i][j]; 50 cout << endl; 51 } 52 } 53 54 int main() 55 { 56 int a, b; 57 cin >> n; 58 string s1, s2; 59 for(int i = 0; i < n; i++) 60 pile[i].push_back(i); 61 while(cin >> s1 >> a >> s2 >> b) 62 { 63 int pa, pb, ha, hb; 64 find_block(a, pa, ha); 65 find_block(b, pb, hb); 66 if (pa == pb) 67 continue; //非法指令 68 if (s2 == "onto") 69 clear_above(pb, hb); 70 if (s1 == "move") 71 clear_above(pa, ha); 72 pile_onto(pa, ha, pb); 73 } 74 print(); 75 return 0; 76 }
vector就像是一个二维不定长数组,只是第一维的大小是固定的,但第二维的大小不固定。vector之间可以直接赋值或者作为函数的返回值,像是“一等公民”一样。
vector<int> pile[30];
pile[m].clear() 清空
pile[m].size() 得到数组长度
pile[m].resize(h) 改变大小
pile[m].push_back(pile[p][i]) ,pile[m].push_back(a) 在尾部添加元素
pile[m].pop_back() 在尾部删除元素
pile[m].empty() 测试是否为空