您的位置:首页 > 其它

uoj #152. 【UR #10】汉诺塔

2016-05-25 08:03 211 查看


#152. 【UR #10】汉诺塔

 统计

 描述
 提交
 自定义测试

picks 博士乘上时光机器,打算回到 2012 年化身马猴烧酒阻止金星凌日,挽救世风日下的 OI 界于水火之中。
但是不幸的是,时光机器出现了一些特殊的故障,picks 博士被传送到了一个未知的时空。为了修理时光机器,他必须要得到一种叫做巴拉拉能量的能源。经过调查,他发现在这个时空中存在着一个被当地人称为魔仙堡的领域,从生活在那儿的小魔仙那里就可以得到足够的巴拉拉能量。
然而在那个时空中,存在着一股强大的势力与善良的小魔仙们敌对——那就是邪恶的黑魔仙们。巴拉拉能量是不能被黑魔仙得到的,否则就会产生严重的后果。为了检验 picks 博士是否是黑魔仙派来窃取巴拉拉能量的奸细,睿智的魔仙女王给 picks 博士出了一道题:
我现在使用巴拉拉能量造了三根柱子(编号分别为 11 到 33)以及 nn 块颜色不同的圆盘(编号为 11 到 nn)。最开始我给定一个 11 到 nn 的排列 AA,我会用巴拉拉能量把这些圆盘放到编号为 11 的柱子上,使得从上到下第 ii 块圆盘的编号是 AiAi。
接着你可以进行若干次操作,每一次操作用两个整数 a,ba,b (1≤a,b≤3,a≠b1≤a,b≤3,a≠b)
来描述,表示这次操作你将会把地 aa 根柱子最上面的圆盘取出,并放到第 bb 根柱子上去(如果当前第 aa 根柱子上不存在圆盘,这次操作将会被小魔仙们忽略)。最终你要使得这 nn 块圆盘在同一根柱子上,且从上到下编号依次递增(最终状态下所有圆盘可以在任意一根柱子上)。
小魔仙们虽然善良,但是他们的耐心并不是无限的,所以你必须在 106106 次操作内完成任务。


输入格式

第一行一个正整数 nn。
第二行是一个 11 到 nn 的排列 AA,相邻数字之间恰有一个空格隔开。


输出格式

第一行输出一个整数 KK(0≤K≤1060≤K≤106)。
接下来 KK 行每行两个整数 ai,biai,bi,按照顺序依次描述你的每一次操作。
如果有多种方案,输出任意一种即可。


样例一


input

3
2 1 3


output

4
1 3
1 2
3 1
2 1


explanation

最开始三根柱子上的圆盘状态分别为(2,1,3),(),()(2,1,3),(),()。
第一次操作后圆盘状态为(1,3),(),(2)(1,3),(),(2)
第二次操作后圆盘状态为(3),(1),(2)(3),(1),(2)
第三次操作后圆盘状态为(2,3),(1),()(2,3),(1),()
第四次操作后圆盘状态为(1,2,3),(),()(1,2,3),(),()
在所有操作结束后,圆盘都在第一根柱子上且从上到下编号依次递增。


样例二

见样例数据下载。


限制与约定

测试点编号nn 的规模
1n≤10n≤10
2
3
4n≤500n≤500
5
6
7n≤10000n≤10000
8
9
10
时间限制:1s1s
空间限制:256MB256MB


下载

样例数据下载

题解:模拟+归并排序

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 1000003
using namespace std;
int r1
,ans
;
int x
,y
,cnt;
int a
,n;
void calc(int &a,int &b,int x)
{
if (x==1) a=3,b=2;
if (x==2) a=1,b=3;
if (x==3) a=1,b=2;
}
void merge(int pos,int l,int r)
{
int mid=(l+r)/2;
if (l==r) return;
int t1,t2;
calc(t1,t2,pos);
for (int i=l;i<=mid;i++) x[++cnt]=pos,y[cnt]=t1;
for (int i=l;i<=mid;i++)
x[++cnt]=t1,y[cnt]=t2;
merge(t2,l,mid);
merge(pos,mid+1,r);
int i=l; int j=mid+1; int k1=l;
while (i<=mid&&j<=r)
{
if (a[i]<=a[j]){
r1[k1]=a[i]; i++; k1++; x[++cnt]=t2,y[cnt]=t1;
}
else r1[k1]=a[j],j++,k1++,x[++cnt]=pos,y[cnt]=t1;
}
while (i<=mid)
{
r1[k1]=a[i]; i++; k1++;
x[++cnt]=t2; y[cnt]=t1;
}
while (j<=r){
r1[k1]=a[j]; j++; k1++;
x[++cnt]=pos; y[cnt]=t1;
}
for (int i=l;i<=r;i++)
a[i]=r1[i],x[++cnt]=t1,y[cnt]=pos;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
merge(1,1,n);
printf("%d\n",cnt);
for (int i=1;i<=cnt;i++)
printf("%d %d\n",x[i],y[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: