PKU 1208 The Blocks Problem(模拟+list应用)
题目大意:原题链接
关键是正确理解题目意思
首先:介绍一下list容器的一些操作:参考链接
list<int> c1;
c1.unique(); 去重。
c1.reverse(); 反转链表。
c1.insert(pos,num); 在pos位置插入元素num。
c1.insert(pos,n,num);在pos位置插入n个元素num。
c1.assign(n,num); 将n个num拷贝赋值给链表c。
c1.sort(); 将链表排序(默认升序)。
c1.swap(c2); 将c1和c2交换。
c1.remove(num); 删除链表中值为num的元素。
c1.push_back(num); 在末尾位置添加一个元素。
c1.pop_back(); 删除最末尾的元素。
c1.push_front(num); 在开始位置添加一个元素。
c1.pop_front(); 删除第一个元素。
c1.erase(pos); 删除pos位置的元素。
按要求模拟木块移动:有n(0<n<25)块block以及5种操作:
move a onto b:在将a搬到b所在的那堆积木上之前,先把a和b上方的积木放回原來的位置
move a over b:在将a搬到b所在的那堆积木上之前,先把a上方的积木放回原來的位罝
pile a onto b : 在将a搬到b所在的那堆积木上之前,先将b上方的积木放回原来的位置
pile a over b : 将包括a本身和a上方的积木一起搬到到b所在的那堆上方(以上三种也都包括a)
quit:结束命令,以上四个操作中,若a和b在同一堆中,则不进行任何操作。
注意:
1.当一个位置的初始箱子移走之后,因为这里没有箱子,其他箱子也不会移到这个位置。
2.数组p[id]=jd表示编号为id的木块放在编号为jd的木块上面
3.void Move(int x,int y)函数中为了保证移动后保持原来的顺序(包括最下方的木块)而利用一个临时变量
#include<list> #include<cstdio> #include<string> #include<iostream> using namespace std; list<int> temp; list<int> lis[25]; int p[25]; void Recover(int x) { int id=p[x]; while(lis[id].back()!=x){ int t=lis[id].back(); p[t]=t;//细节 lis[t].push_back(t); lis[id].pop_back(); } } void Move(int x,int y) { int id=p[x],jd=p[y]; while(lis[id].back()!=x){ temp.push_back(lis[id].back()); lis[id].pop_back(); } p[x]=jd;//细节 lis[jd].push_back(lis[id].back());//正确理解题意保持原来的的顺序 lis[id].pop_back();//清理干净 while(!temp.empty()){ lis[jd].push_back(temp.back()); p[temp.back()]=jd; temp.pop_back(); } } int main() { int n,a,b; string str1,str2; scanf("%d",&n); for(int i=0;i<n;i++){ p[i]=i; lis[i].push_back(i); } while(cin>>str1&&str1!="quit"){ cin>>a>>str2>>b; if(str1=="move"&&str2=="onto"){ Recover(a); Recover(b); Move(a,b); } else if(str1=="move"&&str2=="over"){ Recover(a); Move(a,b); } else if(str1=="pile"&&str2=="onto"){ Recover(b); Move(a,b); } else if(str1=="pile"&&str2=="over") Move(a,b); } for(int i=0;i<n;i++){ printf("%d:",i); while(!lis[i].empty()){ printf(" %d",lis[i].front()); lis[i].pop_front(); } printf("\n"); } }