poj1208 The Blocks Problem(模拟)

原题: 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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值