poj 1208(链表)

传送门

题意:(转自https://www.cnblogs.com/zhurb/p/5839701.html

给定一个长度n,有0~n-1编号的箱子和位置,起始个编号的箱子放在相同编号的位置。

有一系列操作:

move a onto b,将a,b上面的箱子放回初始位置,并将a放到b箱上。

move a over b ,将a上面的箱子放回初始位置,并将a放到b箱最上方。

pile a onto b ,将b上面的箱子放回初始位置,并将a和a上的箱子一起放到b箱上。

pile a over b,将a和a上的箱子一起放到b箱最上方。

要求输出最后每个位置的箱子。

 

题解:

本来不应该有什么难度的,只是基础不扎实的我太菜了......

开5个数组记录每个位置的底层箱子和顶层箱子以及每个箱子的位置、上层、和下层,模拟即可......

 

注意:

让人调了半小时的一个重大失误:

移动整块时不仅要该当前箱子的pos,还要改它上面所有箱子的pos!!!

 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,a,b;
int up[30],down[30],pos[30];
int top[30],base[30];
inline void move(int val,int des) {
	int pre=pos[val],tmp=top[pre];
	if (down[val]==-1) base[pre]=-1;
	up[down[val]]=-1;
	top[pre]=down[val];
//	pos[val]=des;
	for (int i=val;~i;i=up[i])
		pos[i]=des;
	down[val]=top[des];
	up[top[des]]=val;
	top[des]=tmp;
	if (down[val]==-1) base[des]=val;
}
inline void clear(int val) {
	for (int i=up[val];~i;i=up[i])
		move(i,i);
//	for (int i=top[pos[val]];i^val;i=down[i])
//		move(i,i);
}
int main() {
//	freopen("poj 1208.in","r",stdin);
	memset(up,-1,sizeof(up));
	memset(down,-1,sizeof(down));
	scanf("%d",&n);
	for (int i=0;i<n;++i)
		top[i]=base[i]=pos[i]=i;
	char s1[5],s2[5];
	while (scanf("%s",s1)&&s1[0]^'q') {
		scanf("%d%s%d",&a,s2,&b);
		if (s1[0]=='m'&&s2[2]=='t') {//move a onto b
			clear(a);
			clear(b);
			move(a,pos[b]);
		} else if (s1[0]=='m'&&s2[2]=='e') {//move a over b
			clear(a);
			move(a,pos[b]);
		} else if (s1[0]=='p'&&s2[2]=='t') {//pile a onto b
			clear(b);
			move(a,pos[b]);
		} else {//pile a over b
			move(a,pos[b]);
		}
	}
	for (int i=0;i<n;++i) {
		printf("%d: ",i);
		if (base[i]==-1) puts("");
		else {
			for (int cur=base[i];~cur;cur=up[cur])
				printf("%d ",cur);
			puts("");
		}
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值