友链
传送门: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;
}