​​友链​​

传送门:http://poj.org/problem?id=1208

给出一个Block序列,一共有四种对Block的操作,要求给一定数目的指令之后,输出Block序列的最终形态。

通过仔细阅读题目,可以看出:

当指令中含有“​move​”这个字符串时,​Block a​上面的Blocks会被全部清楚并回归其初始位置

当指令中含有字符串“​onto​”时,​Block b​上面的Blocks会被全部清楚并回归其初始位置

能够总结出这一点,这道题就没什么难度了

#include<cstdio>
#include<string>
#include<vector>
#include<iostream>

using namespace std;

const int maxn = 30;
int n;
vector<int> pile[maxn];//vector数组,每个pile[i]就是一个vector

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;
}

//归位操作
void clear_above(int p, int h) {
for(int i = h + 1; i < pile[p].size(); i++) {//从h + 1往后遍历Block所在堆
int b = pile[p][i];
pile[b].push_back(b);
}
pile[p].resize(h + 1);
//被处理的堆只剩下从0到h共h + 1个Block了,将长度重置为h + 1
}

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);
//将a上的所有Blocks全部放到b所在堆上,并重置a所在堆长度,失去了上面的Blocks
//只剩下0~h-1共h个Blocks了
}

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);
//模拟放block的动作,向vector尾部压入十个block
while(cin >> s1 && s1 != "quit") {
cin >> a >> s2 >> b;
/*********************************************
command形式是:
string int string int
如:move a onto b
*********************************************/
int pa, pb, ha, hb;
find_block(a, pa, ha);
find_block(b, pb, hb);
//返回a, b Block的位置,p代表被查找块所处的块堆位置,h代表被查找块在其所在块堆中的位置
if(pa == pb) continue;
//如果等待被操作的两个Block处于同一个堆中,则为非法指令,忽略该条指令,读取下一条指令
if(s2 == "onto") clear_above(pb, hb);
//清除b上面的所有Block
if(s1 == "move") clear_above(pa, ha);
//清除a上面的所有Block
pile_onto(pa, ha, pb);
}
print();
return 0;
}