[UOJ #152][UR #10A]汉诺塔(构造+归并排序)

来源:互联网 发布:云计算机房维护 编辑:程序博客网 时间:2024/06/07 23:26

题目描述

传送门

题解

这是一道构造题,目标是排序可以用归并排序来解。
按照归并排序的方法做就行了,但是要注意一些细节:
1、每次归并排序的时候都要保证序列是原来的顺序,所以不能直接挪,而要用另一个柱子来当中转站。
2、每次递归完成之后要将所有的盘子挪到刚开始放的地方。这一步也需要用一个中转站。
即不能破环归并排序本身的性质,挪的过程中注意中转站的运用即可。

代码

#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int max_n=1e4+5;int n,a[max_n],b[max_n],num;struct hp{int x,y;}step[1000005];inline void mergesort(int l,int r,int from,int now){    int mid=(l+r)>>1;    if (l==r) return;    int nxt,other;    if (now==1)    {        nxt=2; other=3;        for (int i=l;i<=mid;++i)            step[++num].x=1,step[num].y=3;        for (int i=l;i<=mid;++i)            step[++num].x=3,step[num].y=2;    }    else if (now==2)    {        nxt=1; other=3;        for (int i=l;i<=mid;++i)            step[++num].x=2,step[num].y=3;        for (int i=l;i<=mid;++i)            step[++num].x=3,step[num].y=1;    }    else if (now==3)    {        nxt=1; other=2;        for (int i=l;i<=mid;++i)            step[++num].x=3,step[num].y=2;        for (int i=l;i<=mid;++i)            step[++num].x=2,step[num].y=1;    }    mergesort(l,mid,nxt,nxt);    mergesort(mid+1,r,now,now);    int i=l,j=mid+1,k=l;    while (i<=mid&&j<=r)    {        if (a[i]<=a[j])        {            b[k++]=a[i++];            step[++num].x=nxt; step[num].y=other;        }        else        {            b[k++]=a[j++];            step[++num].x=now; step[num].y=other;        }    }    while (i<=mid)     {        b[k++]=a[i++];        step[++num].x=nxt; step[num].y=other;    }    while (j<=r)    {        b[k++]=a[j++];        step[++num].x=now; step[num].y=other;    }    for (int i=l;i<=r;++i)    {        step[++num].x=other; step[num].y=from;    }    for (int i=l;i<=r;++i) a[i]=b[i];}int main(){    scanf("%d",&n);    for (int i=1;i<=n;++i) scanf("%d",&a[i]);    mergesort(1,n,1,1);    printf("%d\n",num);    for (int i=1;i<=num;++i)        printf("%d %d\n",step[i].x,step[i].y);}
0 0
原创粉丝点击