uva110 - Meta-Loopless Sorts

对于不了解的规律题要跳出来从全局看规律。

今天解决了UVa 110 Meta-Loopless Sort。这道题的关键在于生成全排列的同时也需要确定如何进行比较可以得到此种全排列。生成全排列的方法有很多,但是有一种方法最适合此题:

假设我们获得了1~n的全排列,如何获得1~n+1的全排列?对于每个1~n的全排列x(1), x(2), ... x(n),可以看作该排列中有n+1个空位,即,<slot>, x(1), <slot>, x(2), <slot>, ...., x(n), <slot>,于是把x(n+1)分别放入这n+1个空位可以得到从x(1), ... x(n)生成的所有1~n+1的全排列。同时,放入某个空位的同时也就决定了x(n+1)和每个元素的大小关系:

因为有x(1), x(2), ..., x(n),因此有x(1) <= x(2) <= x(3) .... <= x(n),则

x(n) < x(n+1), 则插入生成的排列为x(1), x(2), ..., x(n), x(n+1)
否则,如果x(n-1) < x(n+1), 则插入生成的排列为x(1), x(2), ..., x(n-1), x(n+1), x(n)
....
否则,(此时x(n+1) < x(1)),因此排列为x(n+1), x(1), ..., x(n)--------------------------摘自http://soft.zdnet.com.cn/software_zone/2008/0323/779891.shtml

1a

 2ab

   3abc

       ..........................

   3acb

        ...........................

   3cab

         ...........................

 2ba

   3bac

       ..........................

   3bca

       ..........................

   3cba

        .........................

//#include <iostream>
#include <cstring>
#include<cstdio>
#include<cstdlib>
#include <string>
#include<algorithm>
#define MARK -2147483647
using namespace std;
char chh[10];
int m;char kongo[10][20]={"","  ","    ","      ","        ","          ","            ","              ","                " };
int pri[10],pi,left[10],right[10];
void print(int pre,int cc)
{
    int i;
    int koi;
    if(cc==m+1)
        {
            for(;;){if(left[pre]==0)break;pre=left[pre]; }
            printf("%s",kongo[cc-1]);
            printf("writeln(");
            for(;;)
            {   if(left[pre]==0)
                printf("%c",(char)(pre+'a'-1));
                else  printf(",%c",(char)(pre+'a'-1));
                if(right[pre]==0)break;
                pre=right[pre];
            }
            printf(")\n");return;
        }
    for(;;){if(right[pre]==0)break;pre=right[pre]; }

        for(;;)
        {
            if(right[pre]==0)
            {   printf("%s",kongo[cc-1]);
                printf("if %c < %c then\n",(char)(pre+'a'-1),(char)(cc+'a'-1));
                right[pre]=cc;
                left[cc]=pre;
                print(cc,cc+1);
                right[pre]=0;
                left[cc]=0;
            }
            else
            {   printf("%s",kongo[cc-1]);
                printf("else if %c < %c then\n",(char)(pre+'a'-1),(char)(cc+'a'-1));
                left[right[pre]]=cc;
                right[cc]=right[pre];
                right[pre]=cc;
                left[cc]=pre;
                print(cc,cc+1);
                right[pre]=right[cc];
                left[right[cc]]=pre;
                left[cc]=0;
                right[cc]=0;
            }
            if(left[pre]==0)
            { printf("%s",kongo[cc-1]);
                printf("else\n");
                right[cc]=pre;
                left[pre]=cc;
                print(cc,cc+1);
                left[pre]=0;
                right[cc]=0;
                break;
            }
            pre=left[pre];
        }
    return;
}
int main()
{
// freopen("in.txt","r",stdin);
    int n;
    scanf("%d",&n);int nn=n;
    while(n--)
    {   if(nn!=n+1)printf("\n");
        memset(left,0,sizeof(left));
        memset(right,0,sizeof(right));
        scanf("%d",&m);
        printf("program sort(input,output);\n");
        printf("var\n");
        char ch='a';
        pi=0;
        int i;
        for(i=0; i<m-1; ++i,++ch)
        {
            printf("%c,",ch);
            chh[i]=ch;
        }
        printf("%c : integer;\n",ch);
        chh[i]=ch;
        printf("begin\n");
        printf("  readln(");
        ch='a';
        for(i=0; i<m-1; ++i,++ch)printf("%c,",ch);
        printf("%c);\n",ch);
        if(m==1)printf("  writeln(a)\n");
        else
        print(1,2);
        printf("end.\n");


    }
    return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值