原题: http://poj.org/problem?id=1208
题意:有n个块(编号:0~n-1),并且有n个位置 0 ~ n-1,一开始的时候这个块都放在对应编号的位置上
我们可以对这些块有4种操作
操作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这堆的最上方
注意: 如果数字 a==b或者 a和b在同一堆上,则这个指令是非法指令,我们应该忽略这个指令,跳过这个指令不做操作。
用两个数组来模拟这个过程,最后输出就可以,只是需要细心。
用list<nt>vc[] 数组代表每一位置,我们可以看成一列,移出这一列则是pop_back(),叠放上来则是push_back(),恢复到原来的位置push_front()
用一个int col[]数组记录每一个block所在的列
#include<cstdio>
#include<stdio.h>
#include<string>
#include<memory.h>
#include<list>
using namespace std;
int n;
int col[26];//记录每一个块所在的列
list<int>vc[26];//代表每一个列
int check(int num1,int num2) //检查是否是非法指令
{
if(num1==num2 || col[num1]==col[num2]){
return 0;
}
return 1;
}
void recover(int num1)//恢复Num上面的所有块
{
int t=col[num1];
list<int>::iterator it=vc[t].begin();
int s=0;
for(;it!=vc[t].end();it++)
{
if(*it==num1)
{
it++;
while(it!=vc[t].end())
{
col[*it]=*it;//更新所在列
vc[*it].push_front(*it);//恢复,插入到该列
it++;
s++;
}
break;
}
}
while(s>0)
{
vc[t].pop_back();
s--;
}
}
void moveonto(int num1,int num2)
{
recover(num1);//还原num1上面的
vc[col[num1]].pop_back();
recover(num2);//还原num2上面的
vc[col[num2]].push_back(num1);
col[num1]=col[num2];//更新所在列
}
void moveover(int num1,int num2)
{
recover(num1);
vc[col[num1]].pop_back();
vc[col[num2]].push_back(num1);
col[num1]=col[num2];
}
void pileonto(int num1,int num2)
{
recover(num2);//清理掉b上面的
int tmp=col[num1];
int c=col[num2];
col[num1]=c;
vc[c].push_back(num1);
list<int>::iterator it=vc[tmp].begin();//遍历a上面的
int s=1;
for(;it!=vc[tmp].end();it++)
{
if(*it==num1)
{
it++;
while(it!=vc[tmp].end())
{
vc[c].push_back(*it);//插入到b下面
col[*it]=c;//更新所在列
it++;
s++;
}
break;
}
}
while(s>0)
{
vc[tmp].pop_back();
s--;
}
}
void pileover(int num1,int num2)
{
int tmp=col[num1];
list<int>::iterator it=vc[tmp].begin();//遍历a上面的
int c=col[num2];
vc[c].push_back(num1);
col[num1]=c;
int s=1;
for(; it!=vc[tmp].end();it++)
{
if(*it==num1)
{
it++;
while(it!=vc[tmp].end())
{
vc[c].push_back(*it);//插入到b下面
col[*it]=c;//更新所在列
it++;
s++;
}
break;
}
}
while(s>0)
{
vc[tmp].pop_back();
s--;
}
}
int main()
{
while(~scanf("%d",&n))
{
getchar();
char str[30];
for(int i=0;i<n;i++)
{
vc[i].clear();
col[i]=i;//所在的列
vc[i].push_back(i);
}
while(true)
{
gets(str);
string st(str);
if(str[0]=='q')
{
break;
}
//得到对应的操作数 num1,num2
int pos=5;
int num1=st[pos]-'0';
if(st[pos+1]>='0' && st[pos+1]<='9')
{
num1=num1*10+st[pos+1]-'0';
pos++;
}
pos=pos+7;
int num2=st[pos]-'0';
if(st[pos+1]>='0' && st[pos+1]<='9')
{
num2=num2*10+st[pos+1]-'0';
}
//检查指令是否合格
int flag=check(num1,num2);
if(flag!=0)//合格
{
if(st[0]=='m')
{
if(st.find("onto")!=string::npos)
{
moveonto(num1,num2);
}else{
moveover(num1,num2);
}
}
else if(st[0]=='p')
{
if(st.find("onto")!=string::npos)
{
pileonto(num1,num2);
}else{
pileover(num1,num2);
}
}
}
}
//输出
for(int i=0;i<n;i++)
{
printf("%d:",i);
list<int>::iterator it=vc[i].begin();
while(it!=vc[i].end())
{
printf(" %d",*it);
it++;
}
printf("\n");
}
}
return 0;
}