木块问题-每步详解

在计算机科学中的很多地方都会使用简单,抽象的方法来做分析和实验验究。比如在早期的规划学和机器人学的人工智能研究就利用一个积木世界,让机械臂执行操作积木的任务。
在这个问题中,你将在确定的规则和约束条件下构建一个简单的积木世界。这不是让你来研究怎样达到某种状态,而是编写一个“机械臂程序”来响应有限的命令集。

问题

问题就是分析一系列的命令,告诉机械臂如何操纵放在一个平台上的积木。最初平台上有n个积木(编号由0到n - 1),对于任意的0 ≤ i < n - 1,积木bi都与bi + 1相临,图示如下:

机械臂操作积木的有效指令列举如下:
*move a onto b
a和b都是积木的编号,先将a和b上面所有的积木都放回原处,再将a放在b上。
*move a over b
a和b都是积木的编号,先将a上面所有的积木放回原处,再将a放在b上。(b上原有积木不动)
*pile a onto b
a和b都是积木的编号,将a和其上面所有的积极组成的一摞整体移动到b上。在移动前要先将b上面所有的积极都放回原处。移动的一摞积木要保持原来的顺序不变。
*pile a over b
a和b都是积木的编号,将a和其上面所有的积极组成的一摞整体移动到b所在一摞积木的最上面一个积木上。移动的一摞积木要保持原来的顺序不变。
*quit
结束积木世界的操纵。
当a = b或a和b处在同一摞时,任何企图操作a和b的命令都是非法的。所有非法的命令都要忽略,且不能对当前积木的状态产生作用。

输入

输入由1个整数n开始开始,该整数独占一行,表示积木世界中的积木数量。你可以假定0 < n < 25。
从积木数量值的下一行开始是一系列的命令,每条命令独占一行。你的程序要处理所有的命令直到输入退出命令。
你可以假定所有的命令都按上文所示的格式给出。不会出现语法错误的命令。

输出

以积木世界的最终状态作为输出。每一个原始积木的位置i(0 ≤ i < n,n为积木数量)后面都要紧跟一个冒号。如果至少有一个积木在该位置上,冒号后面都要紧跟一个空格,然后是该位置上所有积木编号的序列。每2个积木的编号之间以一个空格隔开。行尾不能出现多余的空格。
每个积木位置独占一行(即第一行输入的n,对应输出n行数据)。

样例输入

10
move 9 onto 1
move 8 over 1
move 7 over 1
move 6 over 1
pile 8 over 6
pile 8 over 5
move 2 over 1
move 4 over 9
quit

样例输出

0: 0
1: 1 9 2 4
2:
3: 3
4:
5: 5 8 7 6
6:
7:
8:
9:
#include<iostream>
#include<cstdio> 
#include<vector> 
using namespace std;
vector<int>A[1009];int n;//定义一个vector好删除和添加
void find(int t1,int &v1,int &v2,int t2,int &g1,int &g2)//查找位置
{
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<A[i].size();j++)
		{
			if(A[i][j] == t1)//寻找要移动的数的位置
			{
				v1 = i;
				v2 = j;	
			} 
			if(A[i][j] == t2)//寻找要移动的数的位置
			{
				g1 = i;
				g2 = j;	
			}
		}	
	}
}
void mo(int a,int v1,int g1,int b,int v2,int g2)//模拟第一种方案
{
	for(int i=g1+1;i<A[v1].size();++i)
	{
		A[A[v1][i]].push_back(A[v1][i]);//把他t1上的数移到原位置
	} 
	for(int i=g2+1;i<A[v2].size();++i)
	{
		A[A[v2][i]].push_back(A[v2][i]);//把t2上的数移到原位置
	} 
	A[v2].resize(g2+1);//把t2上的数删除
	A[v2].push_back(a);//在t1上加个a
	A[v1].resize(g1);//在g1所在的树上去掉g1也就是a
}
void mr(int a,int v1,int g1,int b,int v2,int g2)//模拟第二种方案
{
	for(int i=g1+1;i<A[v1].size();++i)
	{
		A[A[v1][i]].push_back(A[v1][i]);//把t1上的数移到原位置
	} 
	A[v2].push_back(a);//把a移到v2上
	A[v1].resize(g1);//在v1去掉a也就是g1
}
void ro(int a,int v1,int g1,int b,int v2,int g2)//模拟第三种方案
{
	for(int i=g2+1;i<A[v2].size();++i)
	{
		A[A[v2][i]].push_back(A[v2][i]);//把t2上的数移到原位置
	} 
	A[v2].resize(g2+1);//去掉g2上的数
	for(int i = g1 ;i < A[v1].size();++i)
	{
		A[v2].push_back(A[v1][i]);//把t1上的数移到t2上
	} 
	A[v1].resize(g1);//去掉g1和g1上的数
}
void pr(int a,int v1,int g1,int b,int v2,int g2)//模拟第四种方案
{
	for(int i = g1 ;i < A[v1].size();++i)
	{
		A[v2].push_back(A[v1][i]);//把t1上的数移到t2上
	} 
	A[v1].resize(g1);//去掉g1和g1上的数
}
int main()
{	
	scanf("%d",&n);
	for(int i=0;i<n;++i)
	{
		A[i].push_back(i);//初始化
	} 
	string g1,g2;int t1,t2;
	while(cin>>g1)
	{
		if(g1 == "quit")//结束跳出
		{
			break;
		}
		scanf("%d",&t1);
		cin>>g2;
		scanf("%d",&t2);
		if(t1 == t2)
		{
			continue;
		}
		int v1,v2,r1,r2;
		find(t1,v1,r1,t2,v2,r2);//找每个位置
		if(v1 == v2)
		{
			continue;
		}
		if(g1 == "move")
		{
			if(g2 == "onto")
			{
				mo(t1,v1,r1,t2,v2,r2);//方案一
			}
			else{
				mr(t1,v1,r1,t2,v2,r2);//方案二
			}
		}
		if(g1 == "pile")
		{
			if(g2 == "onto")
			{
				ro(t1,v1,r1,t2,v2,r2);//方案三
			}
			else{
				pr(t1,v1,r1,t2,v2,r2);//方案四
			}
		}
	}
	for(int i=0;i<n;++i)
	{
		printf("%d:",i);
		for(int j=0;j < A[i].size();++j)
		{
			printf(" %d",A[i][j]);输出
		}
		printf("\n");
	}
	return 0;
}

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-lyslyslys

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值