一个FLAG #10# The Blocks Problem
题
例题5-2 木块问题。要区分onto和over,onto是要a与b直接接触,over则不需要。以及,move某木块时,要把它上面的木块全部归位,而pile某木块则不需要。
#include <cstdio> #include <string> #include <vector> #include <iostream> using namespace std; const int maxn = 20; int n; vector<int> pile[maxn]; // 每个pile[i]是一个vector // 找木块a(就是一个序号罢了)所在的pile和height以引用形式返回调用者 void find_block(int a, int &p, int &h) { for (p = 0; p != n; ++p) { for (h = 0; h != pile[p].size(); ++h) { if (pile[p][h] == a) return; // vector也可以用数组的形式访问! } } } // 把第p堆高度为h的木块上方的所有木块移回原位 void clear_above(int p, int h) { for (int i = h + 1; i != pile[p].size(); ++i) { int b = pile[p][i]; pile[b].push_back(b); } pile[p].resize(h + 1); // 只保留 0~ h的位置。不包括h+1!h+1以上的都被移走了 } // 把 第 p堆高度为h及其上方的木块整体移动到p2堆的顶部 void pile_onto(int p, int h, int p2) { for (int i = h; i != pile[p].size(); ++i) { pile[p2].push_back(pile[p][i]); } pile[p].resize(h); // 只保留0~ h-1的位置。 } void print() { for (int i = 0; i != n; ++i) { printf("%d:", i); for (int j = 0; j != pile[i].size(); ++j) { printf(" %d", pile[i][j]); } printf("\n"); } } int main() { int a, b; cin >> n; // 有n 个木块 string s1, s2; for (int i = 0; i != n ; ++i) { pile[i].push_back(i); } while (cin >> s1 >> a >> s2 >> b) { // 例如读入 move 1 onto 2 int pa, pb, ha, hb; find_block(a, pa, ha); find_block(b, pb, hb); // 此时 pa ha 存储着 a所在堆的编号 以及高度 // 同理 pb hb 存储着 b所在堆的编号 以及高度 if (pa == pb) continue; // a 与 b 在同一堆的指令是非法指令 if (s2 == "onto") clear_above(pb, hb); // onto要把 b 上的木块归位 if (s1 == "move") clear_above(pa, ha); // move 要把 a 上的木块归位 pile_onto(pa, ha, pb); } print(); return 0; } /* Sample Input 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 ^Z Sample Output 0: 0 1: 1 9 2 4 2: 3: 3 4: 5: 5 8 7 6 6: 7: 8: 9: */
参考
[1] The Blocks Problem(vector) - 若流芳千古 - 博客园