51NOD搬砖块

课后作业:搬砖块

仿真是计算机科学中的重要研究领域。而你身为一名初级研究员,现在有一个简单的小任务。通过你的仿真程序,模拟以下情况。
在你面前的桌子上有一条机械臂和 n 个砖块。这 n 个砖块按 1,2,…,n−2,n−1,n 顺序依次被编号,并且被排成一行放置在桌上(初始状态)。
在这里插入图片描述
机械臂有以下2种指令:

  1. clear a 把 a 上方的木块全部放回其初始位置
  2. move a over b 把 a 和 a 上方的所有木块(如果有)放在 b 所在木块堆的最上面。
    如果有非法指令(例如:a和b在同一堆),应当忽略,非法指令不会造成任何影响。
    所有操作输入完毕后,从左到右,从下到上输出每个位置的木块编号。

输入格式

第一行:两个整数n,m,n表示桌上初始的木块数量 (2<=n<=25) m表示将要执行的操作数量 随后m行:一条机械臂操作指令​​。(5 <= m <= 10000)

输出格式

输出是桌上木块的的最终状态。 输出共有 n 行,每一行的开头编号为 行数 并紧跟一个冒号。表示编号为 i(1 < i ≤ n,其中n是块数)的木块的最原始位置。 如果该位置上有木块,则从下到上,先输出一个空格再输出木块的编号。

输入样例

10 8
move 8 over 1
move 6 over 1
move 10 over 1
move 3 over 2
move 9 over 2
move 7 over 3
move 9 over 6
clear 10

输出样例

1: 1 8 6 10
2: 2 3
3:
4: 4
5: 5
6:
7: 7
8:
9: 9
10:

样例解释

move 8 over 1 木块8移到木块1上方
move 6 over 1 木块6移到木块1、8上方
move 10 over 1 木块10移到木块1、8、6上方
move 3 over 2 木块3移到木块2上方
move 9 over 2 木块9移到木块2、3上方
move 7 over 3 木块7移到木块2、3、9上方
move 9 over 6 木块9、7移到木块1、8、6、10上方
clear 10 木块10上方的木块9、7回到最初的位置

答案程序

#include<bits/stdc++.h>
using namespace std;
const int N=30;
int n,m;
int l[N];//木块所在的列
int cnt[N];//当前这列有多少木块 
int g[N][N];//目前状态:多少列第几个 
void init(){ 
	for(int i=1;i<=n;i++){
		l[i]=i;
		cnt[i]=1;
		g[i][1]=i;
	}
}
void clear(int a){
	int nl=l[a];//所在列 
	int id=1;//a所在的下标 
	while(g[nl][id]!=a){//找出第几个是a 
		id++;
	} 
	for(int i=id+1;i<=cnt[nl];i++){
		int nm=g[nl][i];//当前木块状态 
		if(nm==nl){//当前木块是当前列
		 	g[nl][id]=nm,id++;//放回木块处理 
		}
		else{
			l[nm]=nm;//转列 
			g[nm][++cnt[nm]]=nm;//放回木块处理
		}
	}
	cnt[nl]=id;//少了a上面的木块
}
void move(int a, int b){
	int nla=l[a],nlb=l[b];
	if(nla==nlb){//同列不变 
		return ;
	} 
	int id=1;
	while(g[nla][id]!=a){//找出第几个是a
		id++;
	} 
	for(int i=id;i<=cnt[nla];i++){
		int nm=g[nla][i];
		l[nm]=nlb;//转列 
		g[nlb][++cnt[nlb]]=nm;//依次放木块 
	}
	cnt[nla]=id-1;//少了a和上面的木块 
}
void print(){
	for(int i=1;i<=n;i++){
		cout<<i<<": ";
		for(int j=1;j<=cnt[i];j++){
			cout<<g[i][j]<<" ";
		}
		puts("");
	}
}
int main(){
	cin>>n>>m;
	init(); 
	while(m--){
		string a;
		int b;
		cin>>a>>b;
		if(a=="clear"){
			clear(b);
		}
		else{
			string c;
			int d;
			cin>>c>>d;
			move(b,d);
		}
	}
	print();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值